diff --git a/vim/vim.symlink/bundle/ultisnips/.bzrignore b/vim/vim.symlink/bundle/ultisnips/.bzrignore new file mode 100644 index 0000000..a64bfd0 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/.bzrignore @@ -0,0 +1,2 @@ +doc/tags +.bzr-repo diff --git a/vim/vim.symlink/bundle/ultisnips/.gitignore b/vim/vim.symlink/bundle/ultisnips/.gitignore new file mode 100644 index 0000000..bb169b4 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.swp +doc/tags diff --git a/vim/vim.symlink/bundle/ultisnips/COPYING.txt b/vim/vim.symlink/bundle/ultisnips/COPYING.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/COPYING.txt @@ -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. + + + Copyright (C) + + 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: + + Copyright (C) + 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/vim/vim.symlink/bundle/ultisnips/ChangeLog b/vim/vim.symlink/bundle/ultisnips/ChangeLog new file mode 100644 index 0000000..7ebb301 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/ChangeLog @@ -0,0 +1,138 @@ +version 3.0 (02-Mar-2014): + - Organisational changes: The project is now hosted on github. Snippets are + now shipped separately - please track honza/vim-snippets. + - UltiSnips is now a drop in replacement for snipMate - it parses snipMate + snippets and expands them emulating snipMates smaller feature set. + - Filetype tab completion for UltiSnipsEdit. + - UltiSnipsEdit now only edits private snippet files. Use UltiSnipsEdit! if + you want to edit shipped files. + - New option 's' which strips trailing whitespace before jumping to next + tabstop + - New option 'a' which converts non-ascii characters into ascii characters + in transformations. + - New keyword in snippet files: priority defines which snippets should + overwrite others. This deprecates the '!' option. + *UltiSnips-adding-snippets* + - Remove common whitespace of visual line selections before inserting in an + indented tabstop. + - Support for overwriting the snippet directory name on a per buffer basis + to support per project snippets. *UltiSnips-snippet-search-path* + - The keymaps for jumping in snippets are now only mapped when a snippet is + active, allowing them to be used for something else otherwise. + - Expanding and jumping no longer overwrites the unnamed register. + - Integration with Valloric/YouCompleteMe and Shougo/neocomplete.vim. + - Other plugins can add sources for snippets to create snippets on the fly. + *UltiSnips-extending* + - Vim functions now indicates if it did any work. + *UltiSnips-trigger-functions* + - For python extensions: UltiSnips adds itself to the sys.path and can be + easily imported if it is available. *UltiSnips-python-module-path* + - A new function giving programmatic access to the snippets currently + available for expansion for other plugins integrating with UltiSnips. + *UltiSnips_SnippetsInCurrentScope* + - New or improved snippets (now in a different repo): all, bib, c, cpp, cs, + d, django, eruby, go, haskell, html, html, htmljinja, java, javascript, + js, ledger, ocaml, perl, php, puppet, python, ruby, scss, sh, tex, vim, + xml, zsh. + +version 2.2 (01-Sep-2012): + - Support to silence Python-not-found warnings. *UltiSnips-python-warning* + - Matchit support for snippet files. + - Improvements to syntax file. + - Various smaller bug fixes. + - New command to manually add a filetype to the list for the current + buffer. *:UltiSnipsAddFiletypes* + - New or improved snippets: all, snippets, haskell, bindzone, python, golang, + json, html, coffee, coffee_jasmine, javascript_jasmine, ruby, php, + markdown. + +version 2.1 (14-Feb-2012): + - Python interpolation access to text from visual selection via snip.v. + - Support for transformations of ${VISUAL} texts. + - New or improved snippets: python, tex, texmath, ruby, rails, html, django + +version 2.0 (05-Feb-2012): + - Backwards incompatible change: Support for normal mode editing. Snippets + are no longer exited when leaving insert mode but only by leaving the + text span of the snippets. This allows usage of normal mode commands and + autoformatting. It also increases compatibility with other plugins. + - Backwards incompatible change: Changed glob patterns for snippets to + behave more like Vim *UltiSnips-adding-snippets* + - Backwards incompatible change: Zero Tabstop is no longer removed in + nested snippets + - Support for ${VISUAL:default text} placeholder. *UltiSnips-visual-placeholder* + - Improved handling of utf-8 characters in files and snippet definitions. + - Full support for :py3. UltiSnips now works with python >= 2.6 or >= 3.2. + - New or improved snippets: python, all + +version 1.6 (30-Dec-2011): + - Significant speed improvements and a few bugs fixed. + - Better handling of non ASCII chars in snippets by assuming UTF-8 encoding + when no other information is available. + - Contributions for UltiSnips are now also accepted on GitHub: https://github.com/SirVer/ultisnips/ + - New or improved snippets: ruby, rails, xhtml + +version 1.5 (24-Sep-2011): + - Some critical bug fixes for new vim versions. + - New or improved snippets: tex, texmath, python, jinja2, go, puppet, xhtml + - Configuration of search path for snippets *UltiSnips-snippet-search-path* + - New parser implementation: A little faster, more flexible and less bugged. + +version 1.4 (17-Jul-2011): + - New or improved snippets: php, html, djangohtml, mako, lua + - Snippets are now listed alphabetically by their trigger, no longer in + order of appearance + - Snippet files are now automatically reloaded when they change. + - Support for other directory names for snippets beside + "UltiSnips" *UltiSnips-snippet-search-path* + - Errors are now shown in a scratch window. + - Now fully supports Windows with python >= 2.6. UltiSnips should now work + on all systems that Vim runs on. + - a syntax file was added for snippets files with nice highlighting. + - snippets definition files now have the filetype 'snippets'. It used to be + 'snippet'. + +version 1.3 (14-Feb-2011): + - Erlang snippets (g0rdin) + - Other VimScripts can now define and immediately expand anonymous snippets + ( *UltiSnips_Anon* ) (Ryan Wooden) + - Other VimScripts can now define new snippets via a function + ( *UltiSnips_AddSnippet* ) (Ryan Wooden) + - New Snippets for eruby and rails (Ches Martin). + - A new Option 't' has been added to snippets that avoid expanding tabstops. + Be also more consistent with how indenting is handled. (Ryan Wooden) + - Added a ftplugin script for .snippets files. Syntax highlighting still + missing. (Rupa Deadwyler) + - Added UltiSnipsReset and UltiSnipsEdit (Idea by JCEB) + +version 1.2 (24-Aug-2010): + - many bugs were fixed + - smode mappings for printable characters are now removed before expanding a + snippet. This is configurable. *UltiSnips-warning-smappings* + - all shipped snippets are now fully compatible with UltiSnips + - added support for global snippets which enhance python interpolation even + more *UltiSnips-globals* + - added support for multi word and regular expression triggers. Very + powerful in combination with python interpolation. + - Python interpolation became much more powerful *UltiSnips-python* + - added support for clearsnippets command *UltiSnips-clearing-snippets* + - added support for option w which is a little more strict than i. + - added support for listing of valid triggers. Defaults to . + - added support for option i (inword expansion) + - extends keyword is now supported on the first line of snippet files. This makes it easy to + define special cases, for example cpp extends c: a cpp trigger is useless + in c, but a c trigger is valuable for cpp. + - UltiSnips now adheres to expandtab and tabstop options of vim + +version 1.1 (21-Jul-2009): + - Made triggers configurable. You can also use the same trigger for + expanding and tabbing. The TextMate configuration and is now + possible. + - Conditional Inserts can now be nested + - Added support for b option. This only considers a snippet at the beginning + of a line ( *UltiSnips-adding-snippets* ) + - Added support for ! option. This overwrites previously defined snippets + with the same tab trigger ( *UltiSnips-adding-snippets* ) + - Support for dotted filetype syntax. Now snippets for more than one filetype + can be active ( *UltiSnips-adding-snippets* ) + diff --git a/vim/vim.symlink/bundle/ultisnips/README.md b/vim/vim.symlink/bundle/ultisnips/README.md new file mode 100644 index 0000000..7dca6c0 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/README.md @@ -0,0 +1,60 @@ +UltiSnips +========= + +UltiSnips is the ultimate solution for snippets in Vim. It has tons of features +and is very fast. + +![GIF Demo](https://raw.github.com/SirVer/ultisnips/master/doc/demo.gif) + +In this demo I am editing a python file. I first expand the `#!` snippet, then +the `class` snippet. The completion menu comes from +[YouCompleteMe](https://github.com/Valloric/YouCompleteMe), UltiSnips also +integrates with [neocomplete](https://github.com/Shougo/neocomplete.vim). I can +jump through placeholders and add text while the snippet inserts text in other +places automatically: when I add `Animal` as a base class, `__init__` gets +updated to call the base class constructor. When I add arguments to the +constructor, they automatically get assigned to instance variables. I then +insert my personal snippet for `print` debugging. Note that I left insert mode, +inserted another snippet and went back to add an additional argument to +`__init__` and the class snippet was still active and added another instance +variable. + +The official home of UltiSnips is at . +Please add pull requests and issues there. + +Quick Start +----------- + +This assumes you are using [Vundle](https://github.com/gmarik/Vundle.vim). Adapt +for your plugin manager of choice. Put this into your `.vimrc`. + + " Track the engine. + Plugin 'SirVer/ultisnips' + + " Snippets are separated from the engine. Add this if you want them: + Plugin 'honza/vim-snippets' + + " Trigger configuration. Do not use if you use https://github.com/Valloric/YouCompleteMe. + let g:UltiSnipsExpandTrigger="" + let g:UltiSnipsJumpForwardTrigger="" + let g:UltiSnipsJumpBackwardTrigger="" + + " If you want :UltiSnipsEdit to split your window. + let g:UltiSnipsEditSplit="vertical" + +UltiSnips comes with comprehensive +[documentation](https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt). +As there are more options and tons of features I suggest you at least skim it. + +Screencasts +----------- + +From a gentle introduction to really advanced in a few minutes. The blog posts +of the screencasts contain more advanced examples of the things +discussed in the videos. + +- [Episode 1: What are snippets and do I need them?](http://www.sirver.net/blog/2011/12/30/first-episode-of-ultisnips-screencast/) +- [Episode 2: Creating Basic Snippets](http://www.sirver.net/blog/2012/01/08/second-episode-of-ultisnips-screencast/) +- [Episode 3: What's new in version 2.0](http://www.sirver.net/blog/2012/02/05/third-episode-of-ultisnips-screencast/) +- [Episode 4: Python Interpolation](http://www.sirver.net/blog/2012/03/31/fourth-episode-of-ultisnips-screencast/) + diff --git a/vim/vim.symlink/bundle/ultisnips/after/plugin/UltiSnips_after.vim b/vim/vim.symlink/bundle/ultisnips/after/plugin/UltiSnips_after.vim new file mode 100644 index 0000000..ca885a6 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/after/plugin/UltiSnips_after.vim @@ -0,0 +1,13 @@ +" File: UltiSnips_after.vim +" Author: Holger Rapp +" Description: Called after everything else to reclaim keys (Needed for +" Supertab) +" Last Modified: July 27, 2009 + +if exists('did_UltiSnips_after') || &cp || version < 700 + finish +endif + +call UltiSnips#map_keys#MapKeys() + +let did_UltiSnips_after=1 diff --git a/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips.vim b/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips.vim new file mode 100644 index 0000000..369da5d --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips.vim @@ -0,0 +1,188 @@ +" File: UltiSnips.vim +" Author: Holger Rapp +" Description: The Ultimate Snippets solution for Vim + +if exists('did_UltiSnips_autoload') || &cp || version < 700 + finish +endif +let did_UltiSnips_autoload=1 + +" Define dummy version of function called by autocommand setup in +" ftdetect/UltiSnips.vim and plugin/UltiSnips.vim. +" If the function isn't defined (probably due to using a copy of vim +" without python support) it would cause an error. +function! UltiSnips#FileTypeChanged() +endfunction +function! UltiSnips#CursorMoved() +endfunction +function! UltiSnips#CursorMoved() +endfunction +function! UltiSnips#LeavingBuffer() +endfunction +function! UltiSnips#LeavingInsertMode() +endfunction + +call UltiSnips#bootstrap#Bootstrap() +if !exists("g:_uspy") + " Delete the autocommands defined in plugin/UltiSnips.vim and + " ftdetect/UltiSnips.vim. + augroup UltiSnips + au! + augroup END + augroup UltiSnipsFileType + au! + augroup END + finish +end + +" FUNCTIONS {{{ +function! s:compensate_for_pum() + """ The CursorMovedI event is not triggered while the popup-menu is visible, + """ and it's by this event that UltiSnips updates its vim-state. The fix is + """ to explicitly check for the presence of the popup menu, and update + """ the vim-state accordingly. + if pumvisible() + exec g:_uspy "UltiSnips_Manager._cursor_moved()" + endif +endfunction + +function! UltiSnips#Edit(bang, ...) + if a:0 == 1 && a:1 != '' + let type = a:1 + else + let type = "" + endif + exec g:_uspy "vim.command(\"let file = '%s'\" % UltiSnips_Manager._file_to_edit(vim.eval(\"type\"), vim.eval('a:bang')))" + + if !len(file) + return + endif + + let mode = 'e' + if exists('g:UltiSnipsEditSplit') + if g:UltiSnipsEditSplit == 'vertical' + let mode = 'vs' + elseif g:UltiSnipsEditSplit == 'horizontal' + let mode = 'sp' + elseif g:UltiSnipsEditSplit == 'context' + let mode = 'vs' + if winwidth(0) <= 2 * (&tw ? &tw : 80) + let mode = 'sp' + endif + endif + endif + exe ':'.mode.' '.escape(file, ' ') +endfunction + +function! UltiSnips#AddFiletypes(filetypes) + exec g:_uspy "UltiSnips_Manager.add_buffer_filetypes('" . a:filetypes . ".all')" + return "" +endfunction + +function! UltiSnips#FileTypeComplete(arglead, cmdline, cursorpos) + let ret = {} + let items = map( + \ split(globpath(&runtimepath, 'syntax/*.vim'), '\n'), + \ 'fnamemodify(v:val, ":t:r")' + \ ) + call insert(items, 'all') + for item in items + if !has_key(ret, item) && item =~ '^'.a:arglead + let ret[item] = 1 + endif + endfor + + return sort(keys(ret)) +endfunction + +function! UltiSnips#ExpandSnippet() + exec g:_uspy "UltiSnips_Manager.expand()" + return "" +endfunction + +function! UltiSnips#ExpandSnippetOrJump() + call s:compensate_for_pum() + exec g:_uspy "UltiSnips_Manager.expand_or_jump()" + return "" +endfunction + +function! UltiSnips#ListSnippets() + exec g:_uspy "UltiSnips_Manager.list_snippets()" + return "" +endfunction + +function! UltiSnips#SnippetsInCurrentScope() + let g:current_ulti_dict = {} + exec g:_uspy "UltiSnips_Manager.snippets_in_current_scope()" + return g:current_ulti_dict +endfunction + +function! UltiSnips#SaveLastVisualSelection() + exec g:_uspy "UltiSnips_Manager._save_last_visual_selection()" + return "" +endfunction + +function! UltiSnips#JumpBackwards() + call s:compensate_for_pum() + exec g:_uspy "UltiSnips_Manager.jump_backwards()" + return "" +endfunction + +function! UltiSnips#JumpForwards() + call s:compensate_for_pum() + exec g:_uspy "UltiSnips_Manager.jump_forwards()" + return "" +endfunction + +function! UltiSnips#FileTypeChanged() + exec g:_uspy "UltiSnips_Manager.reset_buffer_filetypes()" + exec g:_uspy "UltiSnips_Manager.add_buffer_filetypes('" . &ft . "')" + return "" +endfunction + + +function! UltiSnips#AddSnippet(trigger, value, description, options, ...) + " Takes the same arguments as SnippetManager.add_snippet. + echoerr "Deprecated UltiSnips#AddSnippet called. Please use UltiSnips#AddSnippetWithPriority." | sleep 1 + exec g:_uspy "args = vim.eval(\"a:000\")" + exec g:_uspy "trigger = vim.eval(\"a:trigger\")" + exec g:_uspy "value = vim.eval(\"a:value\")" + exec g:_uspy "description = vim.eval(\"a:description\")" + exec g:_uspy "options = vim.eval(\"a:options\")" + exec g:_uspy "UltiSnips_Manager.add_snippet(trigger, value, description, options, *args)" + return "" +endfunction + +function! UltiSnips#AddSnippetWithPriority(trigger, value, description, options, filetype, priority) + exec g:_uspy "trigger = vim.eval(\"a:trigger\")" + exec g:_uspy "value = vim.eval(\"a:value\")" + exec g:_uspy "description = vim.eval(\"a:description\")" + exec g:_uspy "options = vim.eval(\"a:options\")" + exec g:_uspy "filetype = vim.eval(\"a:filetype\")" + exec g:_uspy "priority = vim.eval(\"a:priority\")" + exec g:_uspy "UltiSnips_Manager.add_snippet(trigger, value, description, options, filetype, priority)" + return "" +endfunction + +function! UltiSnips#Anon(value, ...) + " Takes the same arguments as SnippetManager.expand_anon: + " (value, trigger="", description="", options="") + exec g:_uspy "args = vim.eval(\"a:000\")" + exec g:_uspy "value = vim.eval(\"a:value\")" + exec g:_uspy "UltiSnips_Manager.expand_anon(value, *args)" + return "" +endfunction + + +function! UltiSnips#CursorMoved() + exec g:_uspy "UltiSnips_Manager._cursor_moved()" +endf + +function! UltiSnips#LeavingBuffer() + exec g:_uspy "UltiSnips_Manager._leaving_buffer()" +endf + +function! UltiSnips#LeavingInsertMode() + exec g:_uspy "UltiSnips_Manager._leaving_insert_mode()" +endfunction +" }}} diff --git a/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips/bootstrap.vim b/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips/bootstrap.vim new file mode 100644 index 0000000..d5c865c --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips/bootstrap.vim @@ -0,0 +1,84 @@ +let s:SourcedFile=expand("") + +function! UltiSnips#bootstrap#Bootstrap() + if exists('s:did_UltiSnips_bootstrap') + return + endif + let s:did_UltiSnips_bootstrap=1 + + if !exists("g:UltiSnipsUsePythonVersion") + let g:_uspy=":py3 " + if !has("python3") + if !has("python") + if !exists("g:UltiSnipsNoPythonWarning") + echo "UltiSnips requires py >= 2.6 or any py3" + endif + unlet g:_uspy + return + endif + let g:_uspy=":py " + endif + let g:UltiSnipsUsePythonVersion = "" + else + if g:UltiSnipsUsePythonVersion == 2 + let g:_uspy=":py " + else + let g:_uspy=":py3 " + endif + endif + + " Expand our path + exec g:_uspy "import vim, os, sys" + exec g:_uspy "sourced_file = vim.eval('s:SourcedFile')" + exec g:_uspy "while not os.path.exists(os.path.join(sourced_file, 'pythonx')): + \ sourced_file = os.path.dirname(sourced_file)" + exec g:_uspy "module_path = os.path.join(sourced_file, 'pythonx')" + exec g:_uspy "vim.command(\"let g:UltiSnipsPythonPath = '%s'\" % module_path)" + exec g:_uspy "if not hasattr(vim, 'VIM_SPECIAL_PATH'): sys.path.append(module_path)" + exec g:_uspy "from UltiSnips import UltiSnips_Manager" +endfunction + +" The trigger used to expand a snippet. +" NOTE: expansion and forward jumping can, but needn't be the same trigger +if !exists("g:UltiSnipsExpandTrigger") + let g:UltiSnipsExpandTrigger = "" +endif + +" The trigger used to display all triggers that could possible +" match in the current position. +if !exists("g:UltiSnipsListSnippets") + let g:UltiSnipsListSnippets = "" +endif + +" The trigger used to jump forward to the next placeholder. +" NOTE: expansion and forward jumping can, but needn't be the same trigger +if !exists("g:UltiSnipsJumpForwardTrigger") + let g:UltiSnipsJumpForwardTrigger = "" +endif + +" The trigger to jump backward inside a snippet +if !exists("g:UltiSnipsJumpBackwardTrigger") + let g:UltiSnipsJumpBackwardTrigger = "" +endif + +" Should UltiSnips unmap select mode mappings automagically? +if !exists("g:UltiSnipsRemoveSelectModeMappings") + let g:UltiSnipsRemoveSelectModeMappings = 1 +end + +" If UltiSnips should remove Mappings, which should be ignored +if !exists("g:UltiSnipsMappingsToIgnore") + let g:UltiSnipsMappingsToIgnore = [] +endif + +" UltiSnipsEdit will use this variable to decide if a new window +" is opened when editing. default is "normal", allowed are also +" "vertical", "horizontal" +if !exists("g:UltiSnipsEditSplit") + let g:UltiSnipsEditSplit = 'normal' +endif + +" A list of directory names that are searched for snippets. +if !exists("g:UltiSnipsSnippetDirectories") + let g:UltiSnipsSnippetDirectories = [ "UltiSnips" ] +endif diff --git a/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips/map_keys.vim b/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips/map_keys.vim new file mode 100644 index 0000000..a60d00e --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/autoload/UltiSnips/map_keys.vim @@ -0,0 +1,26 @@ +call UltiSnips#bootstrap#Bootstrap() + +function! UltiSnips#map_keys#MapKeys() + if !exists('g:_uspy') + " Do not map keys if bootstrapping failed (e.g. no Python). + return + endif + + " Map the keys correctly + if g:UltiSnipsExpandTrigger == g:UltiSnipsJumpForwardTrigger + + exec "inoremap " . g:UltiSnipsExpandTrigger . " =UltiSnips#ExpandSnippetOrJump()" + exec "snoremap " . g:UltiSnipsExpandTrigger . " :call UltiSnips#ExpandSnippetOrJump()" + else + exec "inoremap " . g:UltiSnipsExpandTrigger . " =UltiSnips#ExpandSnippet()" + exec "snoremap " . g:UltiSnipsExpandTrigger . " :call UltiSnips#ExpandSnippet()" + endif + exec "xnoremap " . g:UltiSnipsExpandTrigger. " :call UltiSnips#SaveLastVisualSelection()gvs" + exec "inoremap " . g:UltiSnipsListSnippets . " =UltiSnips#ListSnippets()" + exec "snoremap " . g:UltiSnipsListSnippets . " :call UltiSnips#ListSnippets()" + + snoremap c + snoremap c + snoremap c + snoremap "_c +endf diff --git a/vim/vim.symlink/bundle/ultisnips/autoload/neocomplete/sources/ultisnips.vim b/vim/vim.symlink/bundle/ultisnips/autoload/neocomplete/sources/ultisnips.vim new file mode 100644 index 0000000..385a779 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/autoload/neocomplete/sources/ultisnips.vim @@ -0,0 +1,35 @@ +let s:save_cpo = &cpo +set cpo&vim + +let s:source = { + \ 'name' : 'ultisnips', + \ 'kind' : 'keyword', + \ 'mark' : '[US]', + \ 'rank' : 8, + \ 'matchers' : + \ (g:neocomplete#enable_fuzzy_completion ? + \ ['matcher_fuzzy'] : ['matcher_head']), + \ 'min_pattern_length' : 1, + \ 'max_candidates' : 20, + \ 'is_volatile': 1, + \ } + +function! s:source.gather_candidates(context) + let suggestions = [] + let snippets = UltiSnips#SnippetsInCurrentScope() + for trigger in keys(snippets) + let description = get(snippets, trigger) + call add(suggestions, { + \ 'word' : trigger, + \ 'menu' : self.mark . ' '. description + \ }) + endfor + return suggestions +endfunction + +function! neocomplete#sources#ultisnips#define() + return s:source +endfunction + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/vim/vim.symlink/bundle/ultisnips/autoload/unite/sources/ultisnips.vim b/vim/vim.symlink/bundle/ultisnips/autoload/unite/sources/ultisnips.vim new file mode 100644 index 0000000..30e2d83 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/autoload/unite/sources/ultisnips.vim @@ -0,0 +1,56 @@ +let s:save_cpo = &cpo +set cpo&vim + +let s:unite_source = { + \ 'name': 'ultisnips', + \ 'hooks': {}, + \ 'action_table': {}, + \ 'default_action': 'expand', + \ } + +let s:unite_source.action_table.preview = { + \ 'description' : 'ultisnips snippets', + \ 'is_quit' : 0, + \ } + +function! s:unite_source.action_table.preview.func(candidate) + " no nice preview at this point, cannot get snippet text + let snippet_preview = a:candidate['word'] + echo snippet_preview +endfunction + +let s:unite_source.action_table.expand = { + \ 'description': 'expand the current snippet', + \ 'is_quit': 1 + \} + +function! s:unite_source.action_table.expand.func(candidate) + let delCurrWord = (getline(".")[col(".")-1] == " ") ? "" : "diw" + exe "normal " . delCurrWord . "a" . a:candidate['trigger'] . " " + call UltiSnips#ExpandSnippet() + return '' +endfunction + +function! s:unite_source.gather_candidates(args, context) + let default_val = {'word': '', 'unite__abbr': '', 'is_dummy': 0, 'source': + \ 'ultisnips', 'unite__is_marked': 0, 'kind': 'command', 'is_matched': 1, + \ 'is_multiline': 0} + let snippet_list = UltiSnips#SnippetsInCurrentScope() + let canditates = [] + for snip in items(snippet_list) + let curr_val = copy(default_val) + let curr_val['word'] = snip[0] . " " . snip[1] + let curr_val['trigger'] = snip[0] + call add(canditates, curr_val) + endfor + return canditates +endfunction + +function! unite#sources#ultisnips#define() + return s:unite_source +endfunction + +"unlet s:unite_source + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/vim/vim.symlink/bundle/ultisnips/ctags/UltiSnips.cnf b/vim/vim.symlink/bundle/ultisnips/ctags/UltiSnips.cnf new file mode 100644 index 0000000..c30aa8b --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/ctags/UltiSnips.cnf @@ -0,0 +1,3 @@ +--langdef=UltiSnips +--langmap=UltiSnips:.snippets +--regex-UltiSnips=/^snippet (.*)/\1/s,snippet/ diff --git a/vim/vim.symlink/bundle/ultisnips/doc/UltiSnips.txt b/vim/vim.symlink/bundle/ultisnips/doc/UltiSnips.txt new file mode 100644 index 0000000..6f1b11d --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/doc/UltiSnips.txt @@ -0,0 +1,1417 @@ +*UltiSnips.txt* For Vim version 7.0 or later. + + The Ultimate Plugin for Snippets in Vim~ + +UltiSnips *snippet* *snippets* *UltiSnips* + +1. Description |UltiSnips-description| + 1.1 Requirements |UltiSnips-requirements| + 1.2 Acknowledgments |UltiSnips-acknowledgments| +2. Installation and Updating |UltiSnips-installnupdate| +3. Settings & Commands |UltiSnips-settings| + 3.1 Commands |UltiSnips-commands| + 3.2 Triggers |UltiSnips-triggers| + 3.2.1 Using your own trigger functions |UltiSnips-trigger-functions| + 3.2.2 Path to Python Module |UltiSnips-python-module-path| + 3.3 Snippet Search Path |UltiSnips-snippet-search-path| + 3.4 Warning About Select Mode Mappings |UltiSnips-warning-smappings| + 3.5 Functions |UltiSnips-functions| + 3.5.1 UltiSnips#AddSnippetWithPriority |UltiSnips#AddSnippetWithPriority| + 3.5.2 UltiSnips#Anon |UltiSnips#Anon| + 3.5.3 UltiSnips#SnippetsInCurrentScope |UltiSnips#SnippetsInCurrentScope| + 3.6 Missing python support |UltiSnips-python-warning| +4. Syntax |UltiSnips-syntax| + 4.1 Adding Snippets |UltiSnips-adding-snippets| + 4.1.1 Character Escaping |UltiSnips-character-escaping| + 4.2 Plaintext Snippets |UltiSnips-plaintext-snippets| + 4.3 Visual Placeholder |UltiSnips-visual-placeholder| + 4.4 Interpolation |UltiSnips-interpolation| + 4.4.1 Shellcode |UltiSnips-shellcode| + 4.4.2 VimScript |UltiSnips-vimscript| + 4.4.3 Python |UltiSnips-python| + 4.4.4 Global Snippets |UltiSnips-globals| + 4.5 Tabstops and Placeholders |UltiSnips-tabstops| + 4.6 Mirrors |UltiSnips-mirrors| + 4.7 Transformations |UltiSnips-transformations| + 4.7.1 Replacement String |UltiSnips-replacement-string| + 4.7.2 Demos |UltiSnips-demos| + 4.8 Clearing snippets |UltiSnips-clearing-snippets| +5. UltiSnips and Other Plugins |UltiSnips-other-plugins| + 5.1 Existing Integrations |UltiSnips-integrations| + 5.2 Extending UltiSnips |UltiSnips-extending| +6. Helping Out |UltiSnips-helping| +7. Contact |UltiSnips-contact| +8. Contributors |UltiSnips-contributors| + +This plugin only works if 'compatible' is not set. +{Vi does not have any of these features} +{only available when |+python| or |+python3| have been enabled at compile time} + + +============================================================================== +1. Description *UltiSnips-description* + +UltiSnips provides snippet management for the Vim editor. A snippet is a short +piece of text that is either re-used often or contains a lot of redundant +text. UltiSnips allows you to insert a snippet with only a few key strokes. +Snippets are common in structured text like source code but can also be used +for general editing like, for example, inserting a signature in an email or +inserting the current date in a text file. + +UltiSnips was developed using the TDD (Test-driven development) philosophy. +This ensures that features do not disappear and bugs do not reappear after +they have been fixed. + +On my blog, http://www.sirver.net, I posted several short screencasts, which +make a great introduction to UltiSnips, illustrating its features and usage. + +http://www.sirver.net/blog/2011/12/30/first-episode-of-ultisnips-screencast/ +http://www.sirver.net/blog/2012/01/08/second-episode-of-ultisnips-screencast/ +http://www.sirver.net/blog/2012/02/05/third-episode-of-ultisnips-screencast/ +http://www.sirver.net/blog/2012/03/31/fourth-episode-of-ultisnips-screencast/ + + +1.1 Requirements *UltiSnips-requirements* +---------------- + +This plugin works with Vim version 7.0 or later. It only works if the +'compatible' setting is not set. + +This plugin requires python >= 2.6. It has been specifically tested using +python 2.7 and python 3.2 but should theoretically work on all versions of +python >= 2.6. + +The Python 2.x or Python 3.x interface must be available. In other words, Vim +must be compiled with either the |+python| feature or the |+python3| feature. +The following commands show how to test if you have python compiled in Vim. +They print '1' if the python version is compiled in, '0' if not. + +Test if Vim is compiled with python version 2.x: > + :echo has("python") +The python version Vim is linked against can be found with: > + :py import sys; print(sys.version) + +Test if Vim is compiled with python version 3.x: > + :echo has("python3") +The python version Vim is linked against can be found with: > + :py3 import sys; print(sys.version) + +Note that Vim is maybe not using your system-wide installed python version, so +make sure to check the Python version inside of Vim. + +UltiSnips attempts to auto-detect which python version is compiled into Vim. +Unfortunately, in some versions of Vim this detection does not work. +In that case you have to explicitly tell UltiSnips which version to use using +the 'UltiSnipsUsePythonVersion' global variable. + +To use python version 2.x: > + let g:UltiSnipsUsePythonVersion = 2 + +To use python version 3.x: > + let g:UltiSnipsUsePythonVersion = 3 + + +1.2 Acknowledgments *UltiSnips-acknowledgments* +------------------- + +UltiSnips was inspired by the snippets feature of TextMate +(http://macromates.com/), the GUI text editor for Mac OS X. Managing snippets +in Vim is not new. I want to thank Michael Sanders, the author of snipMate, +for some implementation details I borrowed from his plugin and for the +permission to use his snippets. + + +============================================================================= +2. Installation and Updating *UltiSnips-installnupdate* + +The recommended way of getting ultisnips is to track SirVer/ultisnips on +github. The master branch is always stable. + +Using Pathogen: *UltiSnips-using-pathogen* + +If you are a pathogen user, you can track the official mirror of UltiSnips on +github: > + + $ cd ~/.vim/ + $ git submodule add git://github.com/SirVer/ultisnips.git bundle/ultisnips + +If you also want the default snippets, also track > + + $ git submodule add https://github.com/honza/vim-snippets.git + +See the pathogen documentation for more details on how to update a bundle. + + +Using a downloaded packet: *UltiSnips-using-a-downloaded-packet* + +Download the packet and unpack into a directory of your choice. Then add this +directory to your Vim runtime path by adding this line to your vimrc file. > + set runtimepath+=~/.vim/ultisnips_rep + +UltiSnips also needs that Vim sources files from the ftdetect/ directory. +Unfortunately, Vim only allows this directory in the .vim directory. You +therefore have to symlink/copy the files: > + mkdir -p ~/.vim/ftdetect/ + ln -s ~/.vim/ultisnips_rep/ftdetect/* ~/.vim/ftdetect/ + +Restart Vim and UltiSnips should work. To access the help, use > + :helptags ~/.vim/ultisnips_rep/doc + :help UltiSnips + +UltiSnips comes without snippets. The default snippets can be found here: +https://github.com/honza/vim-snippets + +============================================================================= +3. Settings & Commands *UltiSnips-settings* + +3.1 Commands *UltiSnips-commands* +------------ + *:UltiSnipsEdit* +The UltiSnipsEdit command opens a private snippet definition file for the +current filetype. If no snippet file exists, a new file is created. If used as +UltiSnipsEdit! all public snippet files are taken into account too. If +multiple files match the search, the user gets to choose the file. + +There are several variables associated with the UltiSnipsEdit command. + + *g:UltiSnipsEditSplit* +g:UltiSnipsEditSplit Defines how the edit window is opened. Possible + values: + |normal| Default. Opens in the current window. + |horizontal| Splits the window horizontally. + |vertical| Splits the window vertically. + |context| Splits the window vertically or + horizontally depending on context. + + *g:UltiSnipsSnippetsDir* +g:UltiSnipsSnippetsDir + Defines the directory private snippet definition + files are stored in. For example, if the variable + is set to "~/.vim/mydir/UltiSnips" and the current + 'filetype' is "cpp", then :UltiSnipsEdit will open + "~/.vim/mydir/UltiSnips/cpp.snippets". Note that + directories named "snippets" are reserved for + snipMate snippets and cannot be used. + + + *:UltiSnipsAddFiletypes* +The UltiSnipsAddFiletypes command allows for explicit merging of other snippet +filetypes for the current buffer. For example, if you edit a .rst file but +also want the Lua snippets to be available you can issue the command > + + :UltiSnipsAddFiletypes rst.lua + +using the dotted filetype syntax. Order is important, the first filetype in +this list will be the one used for UltiSnipsEdit and the list is +ordered by evaluation priority. Consequently, you might add this to your +ftplugin/rails.vim > + + :UltiSnipsAddFiletypes rails.ruby + +I mention rails first because I want to edit rails snippets when using +UltiSnipsEdit and because rails snippets should overwrite equivalent ruby +snippets. The priority will now be rails -> ruby -> all. If you have some +special programming snippets that should have lower priority than your ruby +snippets you can call > + + :UltiSnipsAddFiletypes ruby.programming + +The priority will then be rails -> ruby -> programming -> all. + +3.2 Triggers *UltiSnips-triggers* +------------ + + *g:UltiSnipsExpandTrigger* *g:UltiSnipsListSnippets* + *g:UltiSnipsJumpForwardTrigger* *g:UltiSnipsJumpBackwardTrigger* +You can define the keys used to trigger UltiSnips actions by setting global +variables. Variables define the keys used to expand a snippet, jump forward +and jump backwards within a snippet, and list all available snippets in the +current expand context. The variables with their default values are: > + g:UltiSnipsExpandTrigger + g:UltiSnipsListSnippets + g:UltiSnipsJumpForwardTrigger + g:UltiSnipsJumpBackwardTrigger + +The g:UltiSnipsExpandTrigger and g:UltiSnipsJumpForwardTrigger can be set to +the same value. To simulate TextMate behavior, add the following lines to your +vimrc file. > + let g:UltiSnipsExpandTrigger="" + let g:UltiSnipsJumpForwardTrigger="" + let g:UltiSnipsJumpBackwardTrigger="" + +UltiSnips will only map the jump triggers while a snippet is active to +interfere as little as possible with other mappings. + +The default value for g:UltiSnipsJumpBackwardTrigger interferes with the +built-in complete function: |i_CTRL-X_CTRL-K|. A workaround is to add the +following to your vimrc file or switching to a plugin like Supertab or +YouCompleteMe. > + inoremap + +3.2.1 Using your own trigger functions *UltiSnips-trigger-functions* +-------------------------------------- + +For advanced users there are four functions that you can map directly to a +key and that correspond to some of the triggers previously defined: + g:UltiSnipsExpandTrigger <--> UltiSnips#ExpandSnippet + g:UltiSnipsJumpForwardTrigger <--> UltiSnips#JumpForwards + g:UltiSnipsJumpBackwardTrigger <--> UltiSnips#JumpBackwards + +If you have g:UltiSnipsExpandTrigger and g:UltiSnipsJumpForwardTrigger set +to the same value then the function you are actually going to use is +UltiSnips#ExpandSnippetOrJump. + +Each time any of the functions UltiSnips#ExpandSnippet, +UltiSnips#ExpandSnippet, UltiSnips#JumpBackwards or UltiSnips#JumpBackwards is +called a global variable is set that contains the return value of the +corresponding function. + +The corresponding variables and functions are: +UltiSnips#ExpandSnippet --> g:ulti_expand_res (0: fail, 1: success) +UltiSnips#ExpandSnippetOrJump --> g:ulti_expand_or_jump_res (0: fail, + 1: expand, 2: jump) +UltiSnips#JumpForwards --> g:ulti_jump_forwards_res (0: fail, 1: success) +UltiSnips#JumpBackwards --> g:ulti_jump_backwards_res (0: fail, 1: success) + +To see how these return values may come in handy, suppose that you want to map +a key to expand or jump, but if none of these actions is successful you want +to call another function. UltiSnips already does this automatically for +supertab, but this allows you individual fine tuning of your Tab key usage. + +Usage is as follows: You define a function > + + let g:ulti_expand_or_jump_res = 0 "default value, just set once + function! Ulti_ExpandOrJump_and_getRes() + call UltiSnips#ExpandSnippetOrJump() + return g:ulti_expand_or_jump_res + endfunction + +then you define your mapping as > + + inoremap =(Ulti_ExpandOrJump_and_getRes() > 0)?"":IMAP_Jumpfunc('', 0) + +and if the you can't expand or jump from the current location then the +alternative function IMAP_Jumpfunc('', 0) is called. + +3.2.2 Path to Python module *UltiSnips-python-module-path* +--------------------------- + +For even more advanced usage, you can directly write python functions using +UltiSnip's python modules. + +Here is a small example funtion that expands a snippet: > + + function! s:Ulti_ExpandSnip() + Python << EOF + import sys, vim + from UltiSnips import UltiSnips_Manager + UltiSnips_Manager.expand() + EOF + return "" + endfunction + +3.3 Snippet Search Path *UltiSnips-snippet-search-path* +----------------------- + +UltiSnips snippet definition files are stored in one or more directories. +There are several variables used to indicate those directories and to define +how UltiSnips loads snippets. + +Snippet definition files are stored in snippet directories. A snippet +directory must be a subdirectory of a directory defined in the 'runtimepath' +option. The variable g:UltiSnipsSnippetDirectories defines a list of names +used for snippet directories. Note that "snippets" is reserved for snipMate +snippets and cannot be used. The default is shown below. > + + let g:UltiSnipsSnippetDirectories=["UltiSnips"] + +UltiSnips will search each 'runtimepath' directory for the subdirectory names +defined in g:UltiSnipsSnippetDirectories in the order they are defined. For +example, if you keep your snippets in a .vim subdirectory called +"mycoolsnippets" and you want to make use of the default snippets that come +with UltiSnips, add the following to your vimrc file. > + let g:UltiSnipsSnippetDirectories=["UltiSnips", "mycoolsnippets"] +If you do not want to use the third party snippets that come with plugins, +define the variable accordingly: > + let g:UltiSnipsSnippetDirectories=["mycoolsnippets"] + +You can also redefine the search path on a buffer by buffer basis by setting +the variable b:UltiSnipsSnippetDirectories. This variable takes precedence +over the global variable. + +|UltiSnips-adding-snippets| explains which files are parsed for a given filetype. + + +3.4 Warning About Select Mode Mappings *UltiSnips-warning-smappings* +-------------------------------------- + +Vim's help document for |mapmode-s| states: > + NOTE: Mapping a printable character in Select mode may confuse the user. + It's better to explicitly use :xmap and :smap for printable characters. Or + use :sunmap after defining the mapping. + +However, most Vim plugins, including some default Vim plugins, do not adhere +to this. UltiSnips uses Select mode to mark tabstops in snippets for +overwriting. Existing Visual+Select mode mappings will interfere. Therefore, +UltiSnips issues a |:sunmap| command to remove each Select mode mapping for +printable characters. No other mappings are touched. In particular, UltiSnips +does not change existing normal, insert or visual mode mappings. + +If this behavior is not desired, you can disable it by adding this line to +your vimrc file. > + let g:UltiSnipsRemoveSelectModeMappings = 0 + +If you want to disable this feature for specific mappings only, add them to +the list of mappings to be ignored. For example, the following lines in your +vimrc file will unmap all Select mode mappings except those mappings +containing either the string "somePlugin" or the string "otherPlugin" in its +complete definition as listed by the |:smap| command. > + + let g:UltiSnipsRemoveSelectModeMappings = 1 + let g:UltiSnipsMappingsToIgnore = [ "somePlugin", "otherPlugin" ] + + +3.5 Functions *UltiSnips-functions* +------------- + +UltiSnips provides some functions for extending core functionality. + + + 3.5.1 UltiSnips#AddSnippetWithPriority *UltiSnips#AddSnippetWithPriority* + +The first function is UltiSnips#AddSnippetWithPriority(trigger, value, description, +options, filetyp, priority). It adds a new snippet with the provided trigger, value, +description, and options to the current list of snippets. See +|UltiSnips-syntax| for details on the meaning of the function arguments. The +Priority is a number that defines which snippet should be preferred over +others. See the priority keyword in|UltiSnips-add-snippets|. + + + 3.5.2 UltiSnips#Anon *UltiSnips#Anon* + +The second function is UltiSnips#Anon(value, ...). It expands an anonymous +snippet. Anonymous snippets are defined on the spot, expanded and immediately +discarded again. Anonymous snippets are not added to the global list of +snippets, so they cannot be expanded a second time unless the function is +called again. The function takes three optional arguments, in order: trigger, +description, options. Arguments coincide with the arguments of the +|UltiSnips#AddSnippetWithPriority| function of the same name. The trigger and +options arguments can change the way the snippet expands. The description is +unused at this point. + +An example use case might be this line from a reStructuredText plugin file: + + inoremap $$ $$=UltiSnips#Anon(':latex:\`$1\`', '$$') + +This expands the snippet whenever two $ signs are typed. +Note: The right-hand side of the mapping starts with an immediate retype of +the '$$' trigger and passes '$$' to the function as the trigger argument. +This is required in order for UltiSnips to have access to the characters +typed so it can determine if the trigger matches or not. + + 3.5.3 UltiSnips#SnippetsInCurrentScope *UltiSnips#SnippetsInCurrentScope* + +A third function is UltiSnips#SnippetsInCurrentScope which is the equivalent +of snipmate GetSnipsInCurrentScope function. +This function simply returns a vim dictionary with the snippets whose trigger +matches the current word. +This function does not add any new functionality to ultisnips directly but +allows to use third party plugins to integrate the current available snippets. + +An example of such third party plugin is SnippetCompleteSnipMate which uses +the function GetSnipsInCurrentScope to integrate the current available +snippets with user defined abbreviations and provides these and a completion +menu. +This script is located in +http://www.vim.org/scripts/script.php?script_id=4276. +Note: If you check the above website it lists two dependencies: the +SnippetComplete plugin and snipmate. +You do need the SnippetComplete plugin but you obviously don't need snipmate, +you just have to define the function GetSnipsInCurrentScope. Put the following +in your vimrc: + +function! GetSnipsInCurrentScope() + return UltiSnips#SnippetsInCurrentScope() +endfunction + + +As a second example on how to use this function consider the following +function and mapping definition: + +function! ExpandPossibleShorterSnippet() + if len(UltiSnips#SnippetsInCurrentScope()) == 1 "only one candidate... + let curr_key = keys(UltiSnips#SnippetsInCurrentScope())[0] + normal diw + exe "normal a" . curr_key + exe "normal a " + return 1 + endif + return 0 +endfunction +inoremap =(ExpandPossibleShorterSnippet() == 0? '': UltiSnips#ExpandSnippet()) + +If the trigger for your snippet is lorem, you type lor, and you have no other +snippets whose trigger matches lor then hitting will expand to whatever +lorem expands to. + + +3.6 Warning about missing python support *UltiSnips-python-warning* +---------------------------------------- + +When UltiSnips is loaded, it will check that the running Vim was compiled with +python support. If no support is detected, a warning will be displayed and +loading of UltiSnips will be skipped. + +If you would like to suppress this warning message, you may add the following +line to your vimrc file. + + let g:UltiSnipsNoPythonWarning = 1 + +This may be useful if your Vim configuration files are shared across several +systems where some of them may not have Vim compiled with python support. + +============================================================================= +4. Syntax *UltiSnips-syntax* + +This chapter describes how to write your own snippets and snippet definition +syntax. Examples are used to help illustrate. + + +4.1 Adding Snippets *UltiSnips-adding-snippets* +------------------- + +See |UltiSnips-snippet-search-path| for an explanation of where directories +with snippet definitions should be located. + +Using a strategy similar to how Vim detects |ftplugins|, UltiSnips iterates +over the snippet definition directories looking for files with names of the +following patterns: ft.snippets, ft_*.snippets, or ft/*, where "ft" is the +'filetype' of the current document and "*" is a shell-like wildcard matching +any string including the empty string. The following table shows some typical +snippet filenames and their associated filetype. + + snippet filename filetype ~ + ruby.snippets ruby + perl.snippets perl + c.snippets c + c_my.snippets c + c/a c + c/b.snippets c + all.snippets *all + all/a.snippets *all + +* The 'all' filetype is unique. It represents snippets available for use when +editing any document regardless of the filetype. A date insertion snippet, for +example, would fit well in the all.snippets file. + +UltiSnips understands Vim's dotted filetype syntax. For example, if you define +a dotted filetype for the CUDA C++ framework, e.g. ":set ft=cuda.cpp", then +UltiSnips will search for and activate snippets for both the cuda and cpp +filetypes. + +The snippets file syntax is simple. All lines starting with a # character are +considered comments. Comments are ignored by UltiSnips. Use them to document +snippets. + +A line beginning with the keyword 'extends' provides a way of combining +snippet files. When the 'extends' directive is included in a snippet file, it +instructs UltiSnips to include all snippets from the indicated filetypes. + +The syntax looks like this: > + extends ft1, ft2, ft3 + +For example, the first line in cpp.snippets looks like this: > + extends c +When UltiSnips activates snippets for a cpp file, it first looks for all c +snippets and activates them as well. This is a convenient way to create +specialized snippet files from more general ones. Multiple 'extends' lines are +permitted in a snippet file, and they can be included anywhere in the file. + + +A line beginning with the keyword 'priority' sets the priority for all +snippets defined in the current file after this line. The default priority for +a file is always 0. When a snippet should be expanded, UltiSnips will collect +all snippet definitions from all sources that match the trigger and keep only +the ones with the highest priority. For example, all shipped snippets have a +priority < 0, so that user defined snippets always overwrite shipped snippets. + + +A line beginning with the keyword 'snippet' marks the beginning of snippet +definition and a line starting with the keyword 'endsnippet' marks the end. +The snippet definition is placed between the lines. Here is a snippet of an +'if' statement for the Unix shell (sh) filetype. + + snippet if "if ... then (if)" + if ${2:[[ ${1:condition} ]]}; then + ${0:#statements} + fi + endsnippet + +The start line takes the following form: > + + snippet tab_trigger [ "description" [ options ] ] + +The tab_trigger is required, but the description and options are optional. + +The 'tab_trigger' is the word or string sequence used to trigger the snippet. +Generally a single word is used but the tab_trigger can include spaces. If you +wish to include spaces, you must wrap the tab trigger in quotes. > + + snippet "tab trigger" [ "description" [ options ] ] + +The quotes are not part of the trigger. To activate the snippet type: tab trigger +followed by the snippet expand character. + +It is not technically necessary to use quotes to wrap a trigger with spaces. +Any matching characters will do. For example, this is a valid snippet starting +line. > + snippet !tab trigger! [ "description" [ options ] ] + +Quotes can be included as part of the trigger by wrapping the trigger in +another character. > + snippet !"tab trigger"! [ "description" [ options ] ] + +To activate this snippet one would type: "tab trigger" + +The 'description' is a string describing the trigger. It is helpful for +documenting the snippet and for distinguishing it from other snippets with the +same tab trigger. When a snippet is activated and more than one tab trigger +match, UltiSnips displays a list of the matching snippets with their +descriptions. The user then selects the snippet they want. + +The 'options' control the behavior of the snippet. Options are indicated by +single characters. The 'options' characters for a snippet are combined into +a word without spaces. + +The options currently supported are: > + b Beginning of line - A snippet with this option is expanded only if the + tab trigger is the first word on the line. In other words, if only + whitespace precedes the tab trigger, expand. The default is to expand + snippets at any position regardless of the preceding non-whitespace + characters. + + i In-word expansion - By default a snippet is expanded only if the tab + trigger is the first word on the line or is preceded by one or more + whitespace characters. A snippet with this option is expanded + regardless of the preceding character. In other words, the snippet can + be triggered in the middle of a word. + + w Word boundary - With this option, the snippet is expanded if + the tab trigger start matches a word boundary and the tab trigger end + matches a word boundary. In other words the tab trigger must be + preceded and followed by non-word characters. Word characters are + defined by the 'iskeyword' setting. Use this option, for example, to + permit expansion where the tab trigger follows punctuation without + expanding suffixes of larger words. + + r Regular expression - With this option, the tab trigger is expected to + be a python regular expression. The snippet is expanded if the recently + typed characters match the regular expression. Note: The regular + expression MUST be quoted (or surrounded with another character) like a + multi-word tab trigger (see above) whether it has spaces or not. A + resulting match is passed to any python code blocks in the snippet + definition as the local variable "match". + + t Do not expand tabs - If a snippet definition includes leading tab + characters, by default UltiSnips expands the tab characters honoring + the Vim 'shiftwidth', 'softtabstop', 'expandtab' and 'tabstop' + indentation settings. (For example, if 'expandtab' is set, the tab is + replaced with spaces.) If this option is set, UltiSnips will ignore the + Vim settings and insert the tab characters as is. This option is useful + for snippets involved with tab delimited formats, for example. + + s Remove whitespace immediately before the cursor at the end of a line + before jumping to the next tabstop. This is useful if there is a + tabstop with optional text at the end of a line. + +The end line is the 'endsnippet' keyword on a line by itself. > + + endsnippet + +When parsing snippet files, UltiSnips chops the trailing newline character +from the 'endsnippet' end line. + + + 4.1.1 Character Escaping: *UltiSnips-character-escaping* + +In snippet definitions, the characters '`', '{', '$', '\' and "'" (single +quote) have special meaning. If you want to insert one of these characters +literally, escape them with a backslash, '\'. + + +4.2 Plaintext Snippets *UltiSnips-plaintext-snippets* +---------------------- + +To illustrate plaintext snippets, let's begin with a simple example. You can +try the examples yourself. Simply edit a new file with Vim. Example snippets +will be added to the 'all.snippets' file, so you'll want to open it in Vim for +editing as well. > + ~/.vim/UltiSnips/all.snippets + +Add this snippet to 'all.snippets' and save the file. + +------------------- SNIP ------------------- +snippet bye "My mail signature" +Good bye, Sir. Hope to talk to you soon. +- Arthur, King of Britain +endsnippet +------------------- SNAP ------------------- + +UltiSnips detects when you write changes to a snippets file and automatically +makes the changes active. So in the empty buffer, type the tab trigger 'bye' +and then press the key. + +bye --> +Good bye, Sir. Hope to talk to you soon. +- Arthur, King of Britain + +The word 'bye' will be replaced with the text of the snippet definition. + + +4.3 Visual Placeholder *UltiSnips-visual-placeholder* +---------------------- + +Snippets can contain a special placeholder called ${VISUAL}. The ${VISUAL} +variable is expanded with the text selected just prior to expanding the +snippet. + +To see how a snippet with a ${VISUAL} placeholder works, define a snippet with +the placeholder, use Vim's Visual mode to select some text, and then press the +key you use to trigger expanding a snippet (see g:UltiSnipsExpandTrigger). The +selected text is deleted, and you are dropped into Insert mode. Now type the +snippet tab trigger and press the key to trigger expansion. As the snippet +expands, the previously selected text is printed in place of the ${VISUAL} +placeholder. + +The ${VISUAL} placeholder can contain default text to use when the snippet has +been triggered when not in Visual mode. The syntax is: > + ${VISUAL:default text} + +The ${VISUAL} placeholder can also define a transformation (see +|UltiSnips-transformations|). The syntax is: > + ${VISUAL:default/search/replace/option}. + +Here is a simple example illustrating a visual transformation. The snippet +will take selected text, replace every instance of "should" within it with +"is" , and wrap the result in tags. + +------------------- SNIP ------------------- +snippet t +${VISUAL:inside text/should/is/g} +endsnippet +------------------- SNAP ------------------- + +Start with this line of text: > + this should be cool + +Position the cursor on the word "should", then press the key sequence: viw +(visual mode -> select inner word). Then press , type "t" and press +again. The result is: > + -> this is be cool + +If you expand this snippet while not in Visual mode (e.g., in Insert mode type +t), you will get: > + inside text + + +4.4 Interpolation *UltiSnips-interpolation* +----------------- + + 4.4.1 Shellcode: *UltiSnips-shellcode* + +Snippets can include shellcode. Put a shell command in a snippet and when the +snippet is expanded, the shell command is replaced by the output produced when +the command is executed. The syntax for shellcode is simple: wrap the code in +backticks, '`'. When a snippet is expanded, UltiSnips runs shellcode by first +writing it to a temporary script and then executing the script. The shellcode +is replaced by the standard output. Anything you can run as a script can be +used in shellcode. Include a shebang line, for example, #!/usr/bin/perl, and +your snippet has the ability to run scripts using other programs, perl, for +example. + +Here are some examples. This snippet uses a shell command to insert the +current date. + +------------------- SNIP ------------------- +snippet today +Today is the `date +%d.%m.%y`. +endsnippet +------------------- SNAP ------------------- + +today -> +Today is the 15.07.09. + + +This example inserts the current date using perl. + +------------------- SNIP ------------------- +snippet today +Today is `#!/usr/bin/perl +@a = localtime(); print $a[3] . '.' . $a[4] . '.' . ($a[5]+1900);`. +endsnippet +------------------- SNAP ------------------- +today -> +Today is 15.6.2009. + + + 4.4.2 VimScript: *UltiSnips-vimscript* + +You can also use Vim scripts (sometimes called VimL) in interpolation. The +syntax is similar to shellcode. Wrap the code in backticks and to distinguish +it as a Vim script, start the code with '!v'. Here is an example that counts +the indent of the current line: + +------------------- SNIP ------------------- +snippet indent +Indent is: `!v indent(".")`. +endsnippet +------------------- SNAP ------------------- + (note the 4 spaces in front): indent -> + (note the 4 spaces in front): Indent is: 4. + + + 4.4.3 Python: *UltiSnips-python* + +Python interpolation is by far the most powerful. The syntax is similar to Vim +scripts except code is started with '!p'. Python scripts can be run using the +python shebang '#!/usr/bin/python', but using the '!p' format comes with some +predefined objects and variables, which can simplify and shorten code. For +example, a 'snip' object instance is implied in python code. Python code using +the '!p' indicator differs in another way. Generally when a snippet is +expanded the standard output of code replaces the code. With python code the +value of the 'rv' property of the 'snip' instance replaces the code. Standard +output is ignored. + +The variables automatically defined in python code are: > + + fn - The current filename + path - The complete path to the current file + t - The values of the placeholders, t[1] is the text of ${1}, and so on + snip - UltiSnips.TextObjects.SnippetUtil object instance. Has methods that + simplify indentation handling. + +The 'snip' object provides the following methods: > + + snip.mkline(line="", indent=None): + Returns a line ready to be appended to the result. If indent + is None, then mkline prepends spaces and/or tabs appropriate to the + current 'tabstop' and 'expandtab' variables. + + snip.shift(amount=1): + Shifts the default indentation level used by mkline right by the + number of spaces defined by 'shiftwidth', 'amount' times. + + snip.unshift(amount=1): + Shifts the default indentation level used by mkline left by the + number of spaces defined by 'shiftwidth', 'amount' times. + + snip.reset_indent(): + Resets the indentation level to its initial value. + + snip.opt(var, default): + Checks if the Vim variable 'var' has been set. If so, it returns the + variable's value; otherwise, it returns the value of 'default'. + +The 'snip' object provides some properties as well: > + + snip.rv: + 'rv' is the return value, the text that will replace the python block + in the snippet definition. It is initialized to the empty string. This + deprecates the 'res' variable. + + snip.c: + The text currently in the python block's position within the snippet. + It is set to empty string as soon as interpolation is completed. Thus + you can check if snip.c is != "" to make sure that the interpolation + is only done once. This deprecates the "cur" variable. + + snip.v: + Data related to the ${VISUAL} placeholder. The property has two + attributes: + snip.v.mode ('v', 'V', '^V', see |visual-mode| ) + snip.v.text The text that was selected. + + snip.fn: + The current filename. + + snip.basename: + The current filename with the extension removed. + + snip.ft: + The current filetype. + +For your convenience, the 'snip' object also provides the following +operators: > + + snip >> amount: + Equivalent to snip.shift(amount) + snip << amount: + Equivalent to snip.unshift(amount) + snip += line: + Equivalent to "snip.rv += '\n' + snip.mkline(line)" + +Any variables defined in a python block can be used in other python blocks +that follow within the same snippet. Also, the python modules 'vim', 're', +'os', 'string' and 'random' are pre-imported within the scope of snippet code. +Other modules can be imported using the python 'import' command. + +Python code allows for very flexible snippets. For example, the following +snippet mirrors the first tabstop value on the same line but right aligned and +in uppercase. + +------------------- SNIP ------------------- +snippet wow +${1:Text}`!p snip.rv = (75-2*len(t[1]))*' '+t[1].upper()` +endsnippet +------------------- SNAP ------------------- +wowHello World -> +Hello World HELLO WORLD + +The following snippet uses the regular expression option and illustrates +regular expression grouping using python's match object. It shows that the +expansion of a snippet can depend on the tab trigger used to define the +snippet, and that tab trigger itself can vary. + +------------------- SNIP ------------------- +snippet "be(gin)?( (\S+))?" "begin{} / end{}" br +\begin{${1:`!p +snip.rv = match.group(3) if match.group(2) is not None else "something"`}} + ${2:${VISUAL}} +\end{$1}$0 +endsnippet +------------------- SNAP ------------------- +becenter -> +\begin{center} + +\end{center} +------------------- SNAP ------------------- +be center -> +\begin{center} + +\end{center} + +The second form is a variation of the first; both produce the same result, +but it illustrates how regular expression grouping works. Using regular +expressions in this manner has some drawbacks: +1. If you use the key for both expanding snippets and completion then + if you typed "be form" expecting the completion "be formatted", you + would end up with the above SNAP instead, not what you want. +2. The snippet is harder to read. + + + 4.4.4 Global Snippets: *UltiSnips-globals* + +Global snippets provide a way to reuse common code in multiple snippets. +Currently, only python code is supported. The result of executing the contents +of a global snippet is put into the globals of each python block in the +snippet file. To create a global snippet, use the keyword 'global' in place of +'snippet', and for python code, you use '!p' for the trigger. For example, the +following snippet produces the same output as the last example . However, with +this syntax the 'upper_right' snippet can be reused by other snippets. + +------------------- SNIP ------------------- +global !p +def upper_right(inp): + return (75 - 2 * len(inp))*' ' + inp.upper() +endglobal + +snippet wow +${1:Text}`!p snip.rv = upper_right(t[1])` +endsnippet +------------------- SNAP ------------------- +wowHello World -> +Hello World HELLO WORLD + +Python global functions can be stored in a python module and then imported. +This makes global functions easily accessible to all snippet files. Since Vim +7.4 you can just drop python files into ~/.vim/pythonx and import them +directly inside your snippets. For example to use +~/.vim/pythonx/my_snippets_helpers.py > + + global !p + from my_snippet_helpers import * + endglobals + + +4.4 Tabstops and Placeholders *UltiSnips-tabstops* *UltiSnips-placeholders* +----------------------------- + +Snippets are used to quickly insert reused text into a document. Often the +text has a fixed structure with variable components. Tabstops are used to +simplify modifying the variable content. With tabstops you can easily place +the cursor at the point of the variable content, enter the content you want, +then jump to the next variable component, enter that content, and continue +until all the variable components are complete. + +The syntax for a tabstop is the dollar sign followed by a number, for example, +'$1'. Tabstops start at number 1 and are followed in sequential order. The +'$0' tabstop is a special tabstop. It is always the last tabstop in the +snippet no matter how many tabstops are defined. + +Here is a simple example. + +------------------- SNIP ------------------- +snippet letter +Dear $1, +$0 +Yours sincerely, +$2 +endsnippet +------------------- SNAP ------------------- +letterBenPaulThanks for suggesting UltiSnips!-> +Dear Ben, +Thanks for suggesting UltiSnips! +Yours sincerely, +Paul + +You can use to jump to the next tabstop, and to jump to the +previous. The key was not used for jumping forward because many people +(myself included) use for completion. See |UltiSnips-triggers| for +help on defining different keys for tabstops. + +It is often useful to have some default text for a tabstop. The default text +may be a value commonly used for the variable component, or it may be a word +or phrase that reminds you what is expected for the variable component. To +include default text, the syntax is '${1:value}'. + +The following example illustrates a snippet for the shell 'case' statement. +The tabstops use default values to remind the user of what value is expected. + +------------------- SNIP ------------------- +snippet case +case ${1:word} in + ${2:pattern} ) $0;; +esac +endsnippet +------------------- SNAP ------------------- + +case$option-vverbose=true +case $option in + -v ) verbose=true;; +esac + + +Sometimes it is useful to have a tabstop within a tabstop. To do this, simply +include the nested tabstop as part of the default text. Consider the following +example illustrating an HTML anchor snippet. + +------------------- SNIP ------------------- +snippet a + + $0 + +endsnippet +------------------- SNAP ------------------- + +When this snippet is expanded, the first tabstop has a default value of +'http://www.example.com'. If you want the 'http://' schema, jump to the next +tabstop. It has a default value of 'example.com'. This can be replaced by +typing whatever domain you want. + +agoogle.comGoogle -> + + Google + + +If at the first tabstop you want a different url schema or want to replace the +default url with a named anchor, '#name', for example, just type the value you +want. + +a#topTop -> + + Top + + +In the last example, typing any text at the first tabstop replaces the default +value, including the second tabstop, with the typed text. So the second +tabstop is essentially deleted. When a tabstop jump is triggered, UltiSnips +moves to the next remaining tabstop '$0'. This feature can be used +intentionally as a handy way for providing optional tabstop values to the +user. Here is an example to illustrate. + +------------------- SNIP ------------------- +snippet a + + $0 + +endsnippet +------------------- SNAP ------------------- + +Here, '$1' marks the first tabstop. It is assumed you always want to add a +value for the 'href' attribute. After entering the url and pressing , the +snippet will jump to the second tabstop, '$2'. This tabstop is optional. The +default text is ' class="link"'. You can press to accept the tabstop, +and the snippet will jump to the third tabstop, '$3', and you can enter the +class attribute value, or, at the second tabstop you can press the backspace +key thereby replacing the second tabstop default with an empty string, +essentially removing it. In either case, continue by pressing and the +snippet will jump to the final tabstop inside the anchor. + +ahttp://www.google.comvisitedGoogle -> + + Google + + +ahttp://www.google.comGoogle -> + + Google + + +The default text of tabstops can also contain mirrors, transformations or +interpolation. + + +4.6 Mirrors *UltiSnips-mirrors* +----------- + +Mirrors repeat the content of a tabstop. During snippet expansion when you +enter the value for a tabstop, all mirrors of that tabstop are replaced with +the same value. To mirror a tabstop simply insert the tabstop again using the +"dollar sign followed by a number" syntax, e.g., '$1'. + +A tabstop can be mirrored multiple times in one snippet, and more than one +tabstop can be mirrored in the same snippet. A mirrored tabstop can have a +default value defined. Only the first instance of the tabstop need have a +default value. Mirrored tabstop will take on the default value automatically. + +Mirrors are handy for start-end tags, for example, TeX 'begin' and 'end' tag +labels, XML and HTML tags, and C code #ifndef blocks. Here are some snippet +examples. + +------------------- SNIP ------------------- +snippet env +\begin{${1:enumerate}} + $0 +\end{$1} +endsnippet +------------------- SNAP ------------------- +envitemize -> +\begin{itemize} + +\end{itemize} + +------------------- SNIP ------------------- +snippet ifndef +#ifndef ${1:SOME_DEFINE} +#define $1 +$0 +#endif /* $1 */ +endsnippet +------------------- SNAP ------------------- +ifndefWIN32 -> +#ifndef WIN32 +#define WIN32 + +#endif /* WIN32 */ + + +4.7 Transformations *UltiSnips-transformations* +------------------- + +Note: Transformations are a bit difficult to grasp so this chapter is divided +into two sections. The first describes transformations and their syntax, and +the second illustrates transformations with demos. + +Transformations are like mirrors but instead of just copying text from the +original tabstop verbatim, a regular expression is matched to the content of +the referenced tabstop and a transformation is then applied to the matched +pattern. The syntax and functionality of transformations in UltiSnips follow +very closely to TextMate transformations. + +A transformation has the following syntax: > + ${ + tab_stop_no - The number of the tabstop to reference + regular_expression - The regular expression the value of the referenced + tabstop is matched on + replacement - The replacement string, explained in detail below + options - Options for the regular expression + +The options can be any combination of > + g - global replace + By default, only the first match of the regular expression is + replaced. With this option all matches are replaced. + i - case insensitive + By default, regular expression matching is case sensitive. With this + option, matching is done without regard to case. + a - ascii conversion + By default, transformation are made on the raw utf-8 string. With + this option, matching is done on the corresponding ASCII string + instead, for example 'à' will become 'a'. + This option required the python package 'unidecode'. + +The syntax of regular expressions is beyond the scope of this document. Python +regular expressions are used internally, so the python 're' module can be used +as a guide. See http://docs.python.org/library/re.html. + +The syntax for the replacement string is unique. The next paragraph describes +it in detail. + + + 4.7.1 Replacement String: *UltiSnips-replacement-string* + +The replacement string can contain $no variables, e.g., $1, which reference +matched groups in the regular expression. The $0 variable is special and +yields the whole match. The replacement string can also contain special escape +sequences: > + \u - Uppercase next letter + \l - Lowercase next letter + \U - Uppercase everything till the next \E + \L - Lowercase everything till the next \E + \E - End upper or lowercase started with \L or \U + \n - A newline + \t - A literal tab + +Finally, the replacement string can contain conditional replacements using the +syntax (?no:text:other text). This reads as follows: if the group $no has +matched, insert "text", otherwise insert "other text". "other text" is +optional and if not provided defaults to the empty string, "". This feature +is very powerful. It allows you to add optional text into snippets. + + + 4.7.2 Demos: *UltiSnips-demos* + +Transformations are very powerful but often the syntax is convoluted. +Hopefully the demos below help illustrate transformation features. + +Demo: Uppercase one character +------------------- SNIP ------------------- +snippet title "Title transformation" +${1:a text} +${1/\w+\s*/\u$0/} +endsnippet +------------------- SNAP ------------------- +titlebig small -> +big small +Big small + + +Demo: Uppercase one character and global replace +------------------- SNIP ------------------- +snippet title "Titlelize in the Transformation" +${1:a text} +${1/\w+\s*/\u$0/g} +endsnippet +------------------- SNAP ------------------- +titlethis is a title -> +this is a title +This Is A Title + + +Demo: ASCII transformation +------------------- SNIP ------------------- +snippet ascii "Replace non ascii chars" +${1: an accentued text} +${1/.*/$0/a} +endsnippet +------------------- SNAP ------------------- +asciià la pêche aux moules +à la pêche aux moules +a la peche aux moules + + +Demo: Regular expression grouping + This is a clever c-like printf snippet, the second tabstop is only shown + when there is a format (%) character in the first tabstop. + +------------------- SNIP ------------------- +snippet printf +printf("${1:%s}\n"${1/([^%]|%%)*(%.)?.*/(?2:, :\);)/}$2${1/([^%]|%%)*(%.)?.*/(?2:\);)/} +endsnippet +------------------- SNAP ------------------- +printfHello // End of line -> +printf("Hello\n"); // End of line + +But +printfA is: %sA // End of line -> +printf("A is: %s\n", A); // End of line + + +There are many more examples of what can be done with transformations in the +bundled snippets. + + +4.8 Clearing snippets *UltiSnips-clearing-snippets* + +To remove snippets for the current file type, use the 'clearsnippets' +directive. + +------------------- SNIP ------------------- +clearsnippets +------------------- SNAP ------------------- + +'clearsnippets' removes all snippets with a priority lower than the current +one. For example, the following cleares all snippets that have priority <= 1, +even though the example snippet is defined after the 'clearsnippets'. + +------------------- SNIP ------------------- +priority 1 +clearsnippets + +priority -1 +snippet example "Cleared example" + This will never be expanded. +endsnippet +------------------- SNAP ------------------- + +To clear one or more specific snippet, provide the triggers of the snippets as +arguments to the 'clearsnippets' command. The following example will clear the +snippets 'trigger1' and 'trigger2'. + +------------------- SNIP ------------------- +clearsnippets trigger1 trigger2 +------------------- SNAP ------------------- + + +============================================================================== +5. UltiSnips and Other Plugins *UltiSnips-other-plugins* + +5.1 Existing Integrations *UltiSnips-integrations* +------------------------- + +UltiSnips has built-in support for some common plugins and there are others +that are aware of UltiSnips and use it to improve the user experience. This is +an incomplete list - if you want to have your plugin listed here, just send me +a pull request. + + *UltiSnips-snipMate* + +snipMate - UltiSnips is a drop-in replacement for snipMate. It has many more +features, so porting snippets is still a good idea, but switching has low +friction now. UltiSnips is trying hard to truly emulate snipMate, for example +recursive tabstops are not supported in snipMate snippets (but of course in +UltiSnips snippets). + +YouCompleteMe - comes with out of the box completion support for UltiSnips. It +offers a really nice completion dialogue for snippets. + +neocomplete - UltiSnips ships with a source for neocomplete and therefore +offers out of the box completion dialogue support for it too. + +unite - UltiSnips has a source for unite. As an example of how you can use +it add the following function and mappings to your vimrc: > + + function! UltiSnipsCallUnite() + Unite -start-insert -winheight=100 -immediately -no-empty ultisnips + return '' + endfunction + + inoremap =(pumvisible()? "\C-E>":"")=UltiSnipsCallUnite() + nnoremap a=(pumvisible()? "\C-E>":"")=UltiSnipsCallUnite() + +When typing in either insert or normal mode you will get the unite +interface with matching snippets. Pressing enter will expand the corresponding +snippet. If only one snippet matches the text in front of the cursor will be +expanded when you press the key. + +Supertab - UltiSnips has built-in support for Supertab. Just use a recent +enough version of both plugins and will either expand a snippet or defer +to Supertab for expansion. + +5.2 Extending UltiSnips *UltiSnips-extending* +------------------------- + +UltiSnips allows other plugins to add new snippets on the fly. Since UltiSnips +is written in python, the integration is also on a python basis. A small +example can be found in `test.py`, search for AddNewSnippetSource. Please +contact me on github if you integrate UltiSnips with your plugin so it can be +listed in the docs. + +============================================================================= +6. Helping Out *UltiSnips-helping* + +UltiSnips needs the help of the Vim community to keep improving. Please +consider joining this effort by providing new snippets, new features or bug +reports. + +You can contribute snippets or patches in various ways. The methods are listed +below in order of convenience for me. Please be as convenient as you +can be :) + +* Clone the repository on GitHub (git clone git@github.com:SirVer/ultisnips.git), + make your changes and send a pull request on GitHub. +* Make a patch, report a bug/feature request (see below) and attach the patch + to it. +* Send me an Email with a patch (see Contact section below). +* Send me an Email with the changed files only. + +You can contribute by fixing or reporting bugs in our issue tracker: +https://github.com/sirver/ultisnips/issues + +If you like this plugin, please vote for it on its Vim script page > + http://www.vim.org/scripts/script.php?script_id=2715 +It is life-changing for me. Maybe it is for you too. + + +============================================================================= +7. Contact *UltiSnips-contact* + +You can reach me at SirVer -AT- gmx -ADOT- de. + +This project aims to be the one-for-all solution for Snippets for Vim. If you +miss a feature or find a bug, please contact me or add an issues to our issues +tracker. + +============================================================================= +8. Contributors *UltiSnips-contributors* + +The primary developer of UltiSnips is SirVer (Holger Rapp). The following +individuals have contributed to UltiSnips (in chronological order): + + JCEB - Jan Christoph Ebersbach + Michael Henry + Chris Chambers + Ryan Wooden + rupa - Rupa Deadwyler + Timo Schmiade + blueyed - Daniel Hahler + expelledboy - Anthony Jackson + allait - Alexey Bezhan + peacech - Charles Gunawan + guns - Sung Pae + shlomif - Shlomi Fish + pberndt - Phillip Berndt + thanatermesis-elive - Thanatermesis + rico-ambiescent - Rico Sta. Cruz + Cody Frazer + suy - Alejandro Exojo + grota - Giuseppe Rota + iiijjjii - Jim Karsten + fgalassi - Federico Galassi + lucapette + Psycojoker - Laurent Peuch + aschrab - Aaron Schrab + stardiviner - NagatoPain + skeept - Jorge Rodrigues + buztard + stephenmckinney - Steve McKinney + Pedro Algarvio - s0undt3ch + Eric Van Dewoestine - ervandew + Matt Patterson - fidothe + Mike Morearty - mmorearty + Stanislav Golovanov - JazzCore + David Briscoe - DavidBriscoe + Keith Welch - paralogiki + Zhao Cai - zhaocai + John Szakmeister - jszakmeister + Jonas Diemer - diemer + Romain Giot - rgiot + Sergey Alexandrov - taketwo + Brian Mock - saikobee + Gernot Höflechner - LFDM + Marcelo D Montu - mMontu + Karl Yngve Lervåg - lervag + Pedro Ferrari - petobens + Ches Martin - ches + Christian - Oberon00 + Andrew Ruder - aeruder + Mathias Fußenegger - mfussenegger + Kevin Ballard - kballard + Ahbong Chang - cwahbong + Glenn Griffin - ggriffiniii + + +Thank you for your support. + +vim:tw=78:ts=8:ft=help:norl: diff --git a/vim/vim.symlink/bundle/ultisnips/doc/demo.gif b/vim/vim.symlink/bundle/ultisnips/doc/demo.gif new file mode 100644 index 0000000..32affe4 Binary files /dev/null and b/vim/vim.symlink/bundle/ultisnips/doc/demo.gif differ diff --git a/vim/vim.symlink/bundle/ultisnips/ftdetect/UltiSnips.vim b/vim/vim.symlink/bundle/ultisnips/ftdetect/UltiSnips.vim new file mode 100644 index 0000000..f4a027f --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/ftdetect/UltiSnips.vim @@ -0,0 +1,14 @@ +" This has to be called before ftplugins are loaded. Therefore +" it is here in ftdetect though it maybe shouldn't + +" This is necessary to prevent errors when using vim as a pager. +if exists("vimpager") + finish +endif + +if has("autocmd") + augroup UltiSnipsFileType + au! + autocmd FileType * call UltiSnips#FileTypeChanged() + augroup END +endif diff --git a/vim/vim.symlink/bundle/ultisnips/ftdetect/snippets.vim b/vim/vim.symlink/bundle/ultisnips/ftdetect/snippets.vim new file mode 100644 index 0000000..2a783ce --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/ftdetect/snippets.vim @@ -0,0 +1,4 @@ +" recognize .snippet files +if has("autocmd") + autocmd BufNewFile,BufRead *.snippets setf snippets +endif diff --git a/vim/vim.symlink/bundle/ultisnips/ftplugin/snippets.vim b/vim/vim.symlink/bundle/ultisnips/ftplugin/snippets.vim new file mode 100644 index 0000000..8479a45 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/ftplugin/snippets.vim @@ -0,0 +1,47 @@ +" Set some sane defaults for snippet files + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:save_cpo = &cpo +set cpo&vim + +" Fold by syntax, but open all folds by default +setlocal foldmethod=syntax +setlocal foldlevel=99 + +setlocal commentstring=#%s + +setlocal noexpandtab +setlocal autoindent nosmartindent nocindent + +" Define match words for use with matchit plugin +" http://www.vim.org/scripts/script.php?script_id=39 +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_ignorecase = 0 + let b:match_words = '^snippet\>:^endsnippet\>,^global\>:^endglobal\>,\${:}' + let s:set_match_words = 1 +endif + +" Add TagBar support +let g:tagbar_type_snippets = { + \ 'ctagstype': 'UltiSnips', + \ 'kinds': [ + \ 's:snippets', + \ ], + \ 'deffile': expand(':p:h:h') . '/ctags/UltiSnips.cnf', + \ } + +" don't unset g:tagbar_type_snippets, it serves no purpose +let b:undo_ftplugin = " + \ setlocal foldmethod< foldlevel< commentstring< + \|setlocal expandtab< autoindent< smartindent< cindent< + \|if get(s:, 'set_match_words') + \|unlet! b:match_ignorecase b:match_words s:set_match_words + \|endif + \" + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/vim/vim.symlink/bundle/ultisnips/plugin/UltiSnips.vim b/vim/vim.symlink/bundle/ultisnips/plugin/UltiSnips.vim new file mode 100644 index 0000000..26ac44b --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/plugin/UltiSnips.vim @@ -0,0 +1,72 @@ +" File: UltiSnips.vim +" Author: Holger Rapp +" Description: The Ultimate Snippets solution for Vim +" +" Testing Info: +" See directions at the top of the test.py script located one +" directory above this file. + +if exists('did_UltiSnips_plugin') || &cp || version < 700 + finish +endif + +" The Commands we define. +command! -bang -nargs=? -complete=customlist,UltiSnips#FileTypeComplete UltiSnipsEdit + \ :call UltiSnips#Edit(, ) + +command! -nargs=1 UltiSnipsAddFiletypes :call UltiSnips#AddFiletypes() + +" Backwards compatible functions. Prefer the ones in autoload/. +function! UltiSnips_FileTypeChanged() + echoerr "Deprecated UltiSnips_FileTypeChanged called. Please use UltiSnips#FileTypeChanged." | sleep 1 + return UltiSnips#FileTypeChanged() +endfunction + +function! UltiSnips_ExpandSnippet() + echoerr "Deprecated UltiSnips_ExpandSnippet called. Please use UltiSnips#ExpandSnippet." | sleep 1 + return UltiSnips#ExpandSnippet() +endfunction + +function! UltiSnips_ExpandSnippetOrJump() + echoerr "Deprecated UltiSnips_ExpandSnippetOrJump called. Please use UltiSnips#ExpandSnippetOrJump." | sleep 1 + return UltiSnips#ExpandSnippetOrJump() +endfunction + +function! UltiSnips_SnippetsInCurrentScope() + echoerr "Deprecated UltiSnips_SnippetsInCurrentScope called. Please use UltiSnips#SnippetsInCurrentScope." | sleep 1 + return UltiSnips#SnippetsInCurrentScope() +endfunction + +function! UltiSnips_JumpBackwards() + echoerr "Deprecated UltiSnips_JumpBackwards called. Please use UltiSnips#JumpBackwards." | sleep 1 + return UltiSnips#JumpBackwards() +endfunction + +function! UltiSnips_JumpForwards() + echoerr "Deprecated UltiSnips_JumpForwards called. Please use UltiSnips#JumpForwards." | sleep 1 + return UltiSnips#JumpForwards() +endfunction + +function! UltiSnips_AddSnippet(...) + echoerr "Deprecated UltiSnips_AddSnippet called. Please use UltiSnips#AddSnippetWithPriority." | sleep 1 + return call(function('UltiSnips#AddSnippet'), a:000) +endfunction + +function! UltiSnips_Anon(...) + echoerr "Deprecated UltiSnips_Anon called. Please use UltiSnips#Anon." | sleep 1 + return call(function('UltiSnips#Anon'), a:000) +endfunction + +augroup UltiSnips + au! + au CursorMovedI * call UltiSnips#CursorMoved() + au CursorMoved * call UltiSnips#CursorMoved() + au BufLeave * call UltiSnips#LeavingBuffer() + au InsertLeave * call UltiSnips#LeavingInsertMode() +augroup END + +call UltiSnips#map_keys#MapKeys() + +let did_UltiSnips_plugin=1 + +" vim: ts=8 sts=4 sw=4 diff --git a/vim/vim.symlink/bundle/ultisnips/plugin/snipMate_compatibility.vim b/vim/vim.symlink/bundle/ultisnips/plugin/snipMate_compatibility.vim new file mode 100644 index 0000000..6fcb82c --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/plugin/snipMate_compatibility.vim @@ -0,0 +1,15 @@ +if exists('did_UltiSnips_snipmate_compatibility') + finish +endif +let did_UltiSnips_snipmate_compatibility = 1 + +if ! exists('g:snips_author') + let g:snips_author = "John Doe" +endif + +" Filename function, taken from snipMate.vim +fun! Filename(...) + let filename = expand('%:t:r') + if filename == '' | return a:0 == 2 ? a:2 : '' | endif + return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g') +endf diff --git a/vim/vim.symlink/bundle/ultisnips/pylintrc b/vim/vim.symlink/bundle/ultisnips/pylintrc new file mode 100644 index 0000000..5790281 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pylintrc @@ -0,0 +1,268 @@ +[MASTER] + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +init-hook='import sys; sys.path.append("pythonx/")' + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS,compatibility_py3 + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable= + attribute-defined-outside-init, + fixme, + redefined-builtin, + too-few-public-methods, + too-many-arguments, + too-many-branches, + too-many-instance-attributes, + too-many-locals, + too-many-public-methods, + too-many-return-statements, + too-many-statements, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" + + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=apply,input + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=_?[a-z_][a-z0-9_]{2,50}$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]{2,50}$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]{2,50}$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]{1,50}$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]{1,50}$ + +# Regular expression which should only match correct attribute names in class +# bodies +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,a,b,x,y,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=(__.*__|wrapper) + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=TODO + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the beginning of the name of dummy variables +# (i.e. not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/__init__.py new file mode 100644 index 0000000..9566f08 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/__init__.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Entry point for all thinks UltiSnips.""" + +import vim # pylint:disable=import-error + +from UltiSnips.snippet_manager import SnippetManager + +UltiSnips_Manager = SnippetManager( # pylint:disable=invalid-name + vim.eval('g:UltiSnipsExpandTrigger'), + vim.eval('g:UltiSnipsJumpForwardTrigger'), + vim.eval('g:UltiSnipsJumpBackwardTrigger')) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/_diff.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/_diff.py new file mode 100644 index 0000000..f2a030b --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/_diff.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Commands to compare text objects and to guess how to transform from one to +another.""" + +from collections import defaultdict +import sys + +from UltiSnips import _vim +from UltiSnips.position import Position + +def is_complete_edit(initial_line, original, wanted, cmds): + """Returns true if 'original' is changed to 'wanted' with the edit commands + in 'cmds'. Initial line is to change the line numbers in 'cmds'.""" + buf = original[:] + for cmd in cmds: + ctype, line, col, char = cmd + line -= initial_line + if ctype == "D": + if char != '\n': + buf[line] = buf[line][:col] + buf[line][col+len(char):] + else: + if line + 1 < len(buf): + buf[line] = buf[line] + buf[line+1] + del buf[line+1] + else: + del buf[line] + elif ctype == "I": + buf[line] = buf[line][:col] + char + buf[line][col:] + buf = '\n'.join(buf).split('\n') + return (len(buf) == len(wanted) and + all(j == k for j, k in zip(buf, wanted))) + +def guess_edit(initial_line, last_text, current_text, vim_state): + """ + Try to guess what the user might have done by heuristically looking at + cursor movement, number of changed lines and if they got longer or shorter. + This will detect most simple movements like insertion, deletion of a line + or carriage return. 'initial_text' is the index of where the comparison + starts, 'last_text' is the last text of the snippet, 'current_text' is the + current text of the snippet and 'vim_state' is the cached vim state. + + Returns (True, edit_cmds) when the edit could be guessed, (False, None) + otherwise. + """ + if not len(last_text) and not len(current_text): + return True, () + pos = vim_state.pos + ppos = vim_state.ppos + + # All text deleted? + if (len(last_text) and + (not current_text or + (len(current_text) == 1 and not current_text[0])) + ): + es = [] + if not current_text: + current_text = [''] + for i in last_text: + es.append(("D", initial_line, 0, i)) + es.append(("D", initial_line, 0, "\n")) + es.pop() # Remove final \n because it is not really removed + if is_complete_edit(initial_line, last_text, current_text, es): + return True, es + if ppos.mode == 'v': # Maybe selectmode? + sv = list(map(int, _vim.eval("""getpos("'<")"""))) + sv = Position(sv[1]-1, sv[2]-1) + ev = list(map(int, _vim.eval("""getpos("'>")"""))) + ev = Position(ev[1]-1, ev[2]-1) + if "exclusive" in _vim.eval("&selection"): + ppos.col -= 1 # We want to be inclusive, sorry. + ev.col -= 1 + es = [] + if sv.line == ev.line: + es.append(("D", sv.line, sv.col, + last_text[sv.line - initial_line][sv.col:ev.col+1])) + if sv != pos and sv.line == pos.line: + es.append(("I", sv.line, sv.col, + current_text[sv.line - initial_line][sv.col:pos.col+1])) + if is_complete_edit(initial_line, last_text, current_text, es): + return True, es + if pos.line == ppos.line: + if len(last_text) == len(current_text): # Movement only in one line + llen = len(last_text[ppos.line - initial_line]) + clen = len(current_text[pos.line - initial_line]) + if ppos < pos and clen > llen: # maybe only chars have been added + es = ( + ("I", ppos.line, ppos.col, + current_text[ppos.line - initial_line] + [ppos.col:pos.col]), + ) + if is_complete_edit(initial_line, last_text, current_text, es): + return True, es + if clen < llen: + if ppos == pos: # 'x' or DEL or dt or something + es = ( + ("D", pos.line, pos.col, + last_text[ppos.line - initial_line] + [ppos.col:ppos.col + (llen - clen)]), + ) + if is_complete_edit(initial_line, last_text, + current_text, es): + return True, es + if pos < ppos: # Backspacing or dT dF? + es = ( + ("D", pos.line, pos.col, + last_text[pos.line - initial_line] + [pos.col:pos.col + llen - clen]), + ) + if is_complete_edit(initial_line, last_text, + current_text, es): + return True, es + elif len(current_text) < len(last_text): + # where some lines deleted? (dd or so) + es = [] + for i in range(len(last_text)-len(current_text)): + es.append(("D", pos.line, 0, + last_text[pos.line - initial_line + i])) + es.append(("D", pos.line, 0, '\n')) + if is_complete_edit(initial_line, last_text, + current_text, es): + return True, es + else: + # Movement in more than one line + if ppos.line + 1 == pos.line and pos.col == 0: # Carriage return? + es = (("I", ppos.line, ppos.col, "\n"),) + if is_complete_edit(initial_line, last_text, + current_text, es): + return True, es + return False, None + +def diff(a, b, sline=0): + """ + Return a list of deletions and insertions that will turn 'a' into 'b'. This + is done by traversing an implicit edit graph and searching for the shortest + route. The basic idea is as follows: + + - Matching a character is free as long as there was no + deletion/insertion before. Then, matching will be seen as delete + + insert [1]. + - Deleting one character has the same cost everywhere. Each additional + character costs only have of the first deletion. + - Insertion is cheaper the earlier it happens. The first character is + more expensive that any later [2]. + + [1] This is that world -> aolsa will be "D" world + "I" aolsa instead of + "D" w , "D" rld, "I" a, "I" lsa + [2] This is that "hello\n\n" -> "hello\n\n\n" will insert a newline after + hello and not after \n + """ + d = defaultdict(list) # pylint:disable=invalid-name + seen = defaultdict(lambda: sys.maxsize) + + d[0] = [(0, 0, sline, 0, ())] + cost = 0 + deletion_cost = len(a)+len(b) + insertion_cost = len(a)+len(b) + while True: + while len(d[cost]): + x, y, line, col, what = d[cost].pop() + + if a[x:] == b[y:]: + return what + + if x < len(a) and y < len(b) and a[x] == b[y]: + ncol = col + 1 + nline = line + if a[x] == '\n': + ncol = 0 + nline += 1 + lcost = cost + 1 + if (what and what[-1][0] == "D" and what[-1][1] == line and + what[-1][2] == col and a[x] != '\n'): + # Matching directly after a deletion should be as costly as + # DELETE + INSERT + a bit + lcost = (deletion_cost + insertion_cost)*1.5 + if seen[x+1, y+1] > lcost: + d[lcost].append((x+1, y+1, nline, ncol, what)) + seen[x+1, y+1] = lcost + if y < len(b): # INSERT + ncol = col + 1 + nline = line + if b[y] == '\n': + ncol = 0 + nline += 1 + if (what and what[-1][0] == "I" and what[-1][1] == nline and + what[-1][2]+len(what[-1][-1]) == col and b[y] != '\n' and + seen[x, y+1] > cost + (insertion_cost + ncol) // 2 + ): + seen[x, y+1] = cost + (insertion_cost + ncol) // 2 + d[cost + (insertion_cost + ncol) // 2].append( + (x, y+1, line, ncol, what[:-1] + ( + ("I", what[-1][1], what[-1][2], + what[-1][-1] + b[y]),) + ) + ) + elif seen[x, y+1] > cost + insertion_cost + ncol: + seen[x, y+1] = cost + insertion_cost + ncol + d[cost + ncol + insertion_cost].append((x, y+1, nline, ncol, + what + (("I", line, col, b[y]),)) + ) + if x < len(a): # DELETE + if (what and what[-1][0] == "D" and what[-1][1] == line and + what[-1][2] == col and a[x] != '\n' and + what[-1][-1] != '\n' and + seen[x+1, y] > cost + deletion_cost // 2 + ): + seen[x+1, y] = cost + deletion_cost // 2 + d[cost + deletion_cost // 2].append( + (x+1, y, line, col, what[:-1] + ( + ("D", line, col, what[-1][-1] + a[x]),)) + ) + elif seen[x+1, y] > cost + deletion_cost: + seen[x+1, y] = cost + deletion_cost + d[cost + deletion_cost].append((x+1, y, line, col, what + + (("D", line, col, a[x]),)) + ) + cost += 1 diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/_vim.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/_vim.py new file mode 100644 index 0000000..919b038 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/_vim.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Wrapper functionality around the functions we need from Vim.""" + +import re + +import vim # pylint:disable=import-error +from vim import error # pylint:disable=import-error,unused-import + +from UltiSnips.compatibility import col2byte, byte2col, \ + as_unicode, as_vimencoding +from UltiSnips.position import Position + +class VimBuffer(object): + """Wrapper around the current Vim buffer.""" + + def __getitem__(self, idx): + if isinstance(idx, slice): # Py3 + return self.__getslice__(idx.start, idx.stop) + rv = vim.current.buffer[idx] + return as_unicode(rv) + + def __getslice__(self, i, j): # pylint:disable=no-self-use + rv = vim.current.buffer[i:j] + return [as_unicode(l) for l in rv] + + def __setitem__(self, idx, text): + if isinstance(idx, slice): # Py3 + return self.__setslice__(idx.start, idx.stop, text) + vim.current.buffer[idx] = as_vimencoding(text) + + def __setslice__(self, i, j, text): # pylint:disable=no-self-use + vim.current.buffer[i:j] = [as_vimencoding(l) for l in text] + + def __len__(self): + return len(vim.current.buffer) + + @property + def line_till_cursor(self): # pylint:disable=no-self-use + """Returns the text before the cursor.""" + # Note: we want byte position here + _, col = vim.current.window.cursor + line = vim.current.line + before = as_unicode(line[:col]) + return before + + @property + def number(self): # pylint:disable=no-self-use + """The bufnr() of this buffer.""" + return int(eval("bufnr('%')")) + + @property + def cursor(self): # pylint:disable=no-self-use + """ + The current windows cursor. Note that this is 0 based in col and 0 + based in line which is different from Vim's cursor. + """ + line, nbyte = vim.current.window.cursor + col = byte2col(line, nbyte) + return Position(line - 1, col) + + @cursor.setter + def cursor(self, pos): # pylint:disable=no-self-use + """See getter.""" + nbyte = col2byte(pos.line + 1, pos.col) + vim.current.window.cursor = pos.line + 1, nbyte +buf = VimBuffer() # pylint:disable=invalid-name + +def escape(inp): + """Creates a vim-friendly string from a group of + dicts, lists and strings.""" + def conv(obj): + """Convert obj.""" + if isinstance(obj, list): + rv = as_unicode('[' + ','.join(conv(o) for o in obj) + ']') + elif isinstance(obj, dict): + rv = as_unicode('{' + ','.join([ + "%s:%s" % (conv(key), conv(value)) + for key, value in obj.iteritems()]) + '}') + else: + rv = as_unicode('"%s"') % as_unicode(obj).replace('"', '\\"') + return rv + return conv(inp) + +def command(cmd): + """Wraps vim.command.""" + return as_unicode(vim.command(as_vimencoding(cmd))) + +def eval(text): + """Wraps vim.eval.""" + rv = vim.eval(as_vimencoding(text)) + if not isinstance(rv, (dict, list)): + return as_unicode(rv) + return rv + +def feedkeys(keys, mode='n'): + """Wrapper around vim's feedkeys function. Mainly for convenience.""" + command(as_unicode(r'call feedkeys("%s", "%s")') % (keys, mode)) + +def new_scratch_buffer(text): + """Create a new scratch buffer with the text given""" + vim.command("botright new") + vim.command("set ft=") + vim.command("set buftype=nofile") + + vim.current.buffer[:] = text.splitlines() + + feedkeys(r"\") + +def virtual_position(line, col): + """Runs the position through virtcol() and returns the result.""" + nbytes = col2byte(line, col) + return line, int(eval('virtcol([%d, %d])' % (line, nbytes))) + +def select(start, end): + """Select the span in Select mode""" + _unmap_select_mode_mapping() + + selection = eval("&selection") + + col = col2byte(start.line + 1, start.col) + vim.current.window.cursor = start.line + 1, col + + move_cmd = "" + if eval("mode()") != 'n': + move_cmd += r"\" + + if start == end: + # Zero Length Tabstops, use 'i' or 'a'. + if col == 0 or eval("mode()") not in 'i' and \ + col < len(buf[start.line]): + move_cmd += "i" + else: + move_cmd += "a" + else: + # Non zero length, use Visual selection. + move_cmd += "v" + if "inclusive" in selection: + if end.col == 0: + move_cmd += "%iG$" % end.line + else: + move_cmd += "%iG%i|" % virtual_position(end.line + 1, end.col) + elif "old" in selection: + move_cmd += "%iG%i|" % virtual_position(end.line + 1, end.col) + else: + move_cmd += "%iG%i|" % virtual_position(end.line + 1, end.col + 1) + move_cmd += "o%iG%i|o\\" % virtual_position( + start.line + 1, start.col + 1) + feedkeys(_LangMapTranslator().translate(move_cmd)) + +def _unmap_select_mode_mapping(): + """This function unmaps select mode mappings if so wished by the user. + Removes select mode mappings that can actually be typed by the user + (ie, ignores things like ). + """ + if int(eval("g:UltiSnipsRemoveSelectModeMappings")): + ignores = eval("g:UltiSnipsMappingsToIgnore") + ['UltiSnips'] + + for option in ("", ""): + # Put all smaps into a var, and then read the var + command(r"redir => _tmp_smaps | silent smap %s " % option + + "| redir END") + + # Check if any mappings where found + all_maps = list(filter(len, eval(r"_tmp_smaps").splitlines())) + if len(all_maps) == 1 and all_maps[0][0] not in " sv": + # "No maps found". String could be localized. Hopefully + # it doesn't start with any of these letters in any + # language + continue + + # Only keep mappings that should not be ignored + maps = [m for m in all_maps if + not any(i in m for i in ignores) and len(m.strip())] + + for map in maps: + # The first three chars are the modes, that might be listed. + # We are not interested in them here. + trig = map[3:].split()[0] if len(map[3:].split()) != 0 else None + + if trig is None: + continue + + # The bar separates commands + if trig[-1] == "|": + trig = trig[:-1] + "" + + # Special ones + if trig[0] == "<": + add = False + # Only allow these + for valid in ["Tab", "NL", "CR", "C-Tab", "BS"]: + if trig == "<%s>" % valid: + add = True + if not add: + continue + + # UltiSnips remaps . Keep this around. + if trig == "": + continue + + # Actually unmap it + try: + command("silent! sunmap %s %s" % (option, trig)) + except: # pylint:disable=bare-except + # Bug 908139: ignore unmaps that fail because of + # unprintable characters. This is not ideal because we + # will not be able to unmap lhs with any unprintable + # character. If the lhs stats with a printable + # character this will leak to the user when he tries to + # type this character as a first in a selected tabstop. + # This case should be rare enough to not bother us + # though. + pass + +class _RealLangMapTranslator(object): + """This cares for the Vim langmap option and basically reverses the + mappings. This was the only solution to get UltiSnips to work nicely with + langmap; other stuff I tried was using inoremap movement commands and + caching and restoring the langmap option. + + Note that this will not work if the langmap overwrites a character + completely, for example if 'j' is remapped, but nothing is mapped back to + 'j', then moving one line down is no longer possible and UltiSnips will + fail. + """ + _maps = {} + _SEMICOLONS = re.compile(r"(? 1: + from_char, to_char = [a.replace("\\;", ";") for a in res] + from_chars += from_char + to_chars += to_char + else: + from_chars += char[::2] + to_chars += char[1::2] + self._maps[langmap] = (from_chars, to_chars) + + def translate(self, text): + """Inverse map 'text' through langmap.""" + langmap = eval("&langmap").strip() + if langmap == "": + return text + text = as_unicode(text) + if langmap not in self._maps: + self._create_translation(langmap) + for before, after in zip(*self._maps[langmap]): + text = text.replace(before, after) + return text + +class _DummyLangMapTranslator(object): + """If vim hasn't got the langmap compiled in, we never have to do anything. + Then this class is used. """ + translate = lambda self, s: s + +_LangMapTranslator = _RealLangMapTranslator +if not int(eval('has("langmap")')): + _LangMapTranslator = _DummyLangMapTranslator diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/compatibility.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/compatibility.py new file mode 100644 index 0000000..c8c975e --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/compatibility.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# encoding: utf-8 + +""" +This file contains compatibility code to stay compatible with +as many python versions as possible. +""" + +import sys + +import vim # pylint:disable=import-error + +if sys.version_info >= (3, 0): + def _vim_dec(string): + """Decode 'string' using &encoding.""" + # We don't have the luxury here of failing, everything + # falls apart if we don't return a bytearray from the + # passed in string + return string.decode(vim.eval("&encoding"), "replace") + + def _vim_enc(bytearray): + """Encode 'string' using &encoding.""" + # We don't have the luxury here of failing, everything + # falls apart if we don't return a string from the passed + # in bytearray + return bytearray.encode(vim.eval("&encoding"), "replace") + + def open_ascii_file(filename, mode): + """Opens a file in "r" mode.""" + return open(filename, mode, encoding="utf-8") + + def col2byte(line, col): + """ + Convert a valid column index into a byte index inside + of vims buffer. + """ + # We pad the line so that selecting the +1 st column still works. + pre_chars = (vim.current.buffer[line-1] + " ")[:col] + return len(_vim_enc(pre_chars)) + + def byte2col(line, nbyte): + """ + Convert a column into a byteidx suitable for a mark or cursor + position inside of vim + """ + line = vim.current.buffer[line-1] + raw_bytes = _vim_enc(line)[:nbyte] + return len(_vim_dec(raw_bytes)) + + def as_unicode(string): + """Return 'string' as unicode instance.""" + if isinstance(string, bytes): + return _vim_dec(string) + return str(string) + + def as_vimencoding(string): + """Return 'string' as Vim internal encoding.""" + return string +else: + import warnings + warnings.filterwarnings("ignore", category=DeprecationWarning) + + def _vim_dec(string): + """Decode 'string' using &encoding.""" + try: + return string.decode(vim.eval("&encoding")) + except UnicodeDecodeError: + # At least we tried. There might be some problems down the road now + return string + + def _vim_enc(string): + """Encode 'string' using &encoding.""" + try: + return string.encode(vim.eval("&encoding")) + except UnicodeEncodeError: + return string + + def open_ascii_file(filename, mode): + """Opens a file in "r" mode.""" + return open(filename, mode) + + def col2byte(line, col): + """ + Convert a valid column index into a byte index inside + of vims buffer. + """ + # We pad the line so that selecting the +1 st column still works. + pre_chars = _vim_dec(vim.current.buffer[line-1] + " ")[:col] + return len(_vim_enc(pre_chars)) + + def byte2col(line, nbyte): + """ + Convert a column into a byteidx suitable for a mark or cursor + position inside of vim + """ + line = vim.current.buffer[line-1] + if nbyte >= len(line): # This is beyond end of line + return nbyte + return len(_vim_dec(line[:nbyte])) + + def as_unicode(string): + """Return 'string' as unicode instance.""" + if isinstance(string, str): + return _vim_dec(string) + return unicode(string) + + def as_vimencoding(string): + """Return 'string' as unicode instance.""" + return _vim_enc(string) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/debug.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/debug.py new file mode 100644 index 0000000..10c34ec --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/debug.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Convenience methods that help with debugging. They should never be used in +production code.""" + +import sys + +from UltiSnips.compatibility import as_unicode + +DUMP_FILENAME = "/tmp/file.txt" if not sys.platform.lower().startswith("win") \ + else "C:/windows/temp/ultisnips.txt" +with open(DUMP_FILENAME, "w"): + pass # clears the file + +def echo_to_hierarchy(text_object): + """Outputs the given 'text_object' and its children hierarchically.""" + # pylint:disable=protected-access + parent = text_object + while parent._parent: + parent = parent._parent + + def _do_print(text_object, indent=""): + """prints recursively.""" + debug(indent + as_unicode(text_object)) + try: + for child in text_object._children: + _do_print(child, indent=indent + " ") + except AttributeError: + pass + _do_print(parent) + +def debug(msg): + """Dumb 'msg' into the debug file.""" + msg = as_unicode(msg) + with open(DUMP_FILENAME, "ab") as dump_file: + dump_file.write((msg + '\n').encode("utf-8")) + +def print_stack(): + """Dump a stack trace into the debug file.""" + import traceback + with open(DUMP_FILENAME, "ab") as dump_file: + traceback.print_stack(file=dump_file) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/indent_util.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/indent_util.py new file mode 100644 index 0000000..cffa15e --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/indent_util.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""See module doc.""" + +from UltiSnips import _vim + +class IndentUtil(object): + """Utility class for dealing properly with indentation. """ + + def __init__(self): + self.reset() + + def reset(self): + """ Gets the spacing properties from Vim. """ + self.shiftwidth = int(_vim.eval("exists('*shiftwidth') ? shiftwidth() : &shiftwidth")) + self._expandtab = (_vim.eval("&expandtab") == "1") + self._tabstop = int(_vim.eval("&tabstop")) + + def ntabs_to_proper_indent(self, ntabs): + """Convert 'ntabs' number of tabs to the proper indent prefix.""" + line_ind = ntabs * self.shiftwidth * " " + line_ind = self.indent_to_spaces(line_ind) + line_ind = self.spaces_to_indent(line_ind) + return line_ind + + def indent_to_spaces(self, indent): + """ Converts indentation to spaces respecting Vim settings. """ + indent = indent.expandtabs(self._tabstop) + right = (len(indent) - len(indent.rstrip(" "))) * " " + indent = indent.replace(" ", "") + indent = indent.replace('\t', " " * self._tabstop) + return indent + right + + def spaces_to_indent(self, indent): + """ Converts spaces to proper indentation respecting Vim settings """ + if not self._expandtab: + indent = indent.replace(" " * self._tabstop, '\t') + return indent diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/position.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/position.py new file mode 100644 index 0000000..d22d04f --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/position.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Represents a Position in a text file: (0 based line index, 0 based column +index) and provides methods for moving them around.""" + +class Position(object): + """See module docstring.""" + + def __init__(self, line, col): + self.line = line + self.col = col + + def move(self, pivot, delta): + """'pivot' is the position of the first changed character, 'delta' is + how text after it moved""" + if self < pivot: + return + if delta.line == 0: + if self.line == pivot.line: + self.col += delta.col + elif delta.line > 0: + if self.line == pivot.line: + self.col += delta.col - pivot.col + self.line += delta.line + else: + self.line += delta.line + if self.line == pivot.line: + self.col += - delta.col + pivot.col + + def delta(self, pos): + """Returns the difference that the cursor must move to come from 'pos' + to us.""" + assert isinstance(pos, Position) + if self.line == pos.line: + return Position(0, self.col - pos.col) + else: + if self > pos: + return Position(self.line - pos.line, self.col) + else: + return Position(self.line - pos.line, pos.col) + return Position(self.line - pos.line, self.col - pos.col) + + def __add__(self, pos): + assert isinstance(pos, Position) + return Position(self.line + pos.line, self.col + pos.col) + + def __sub__(self, pos): + assert isinstance(pos, Position) + return Position(self.line - pos.line, self.col - pos.col) + + def __eq__(self, other): + return (self.line, self.col) == (other.line, other.col) + + def __ne__(self, other): + return (self.line, self.col) != (other.line, other.col) + + def __lt__(self, other): + return (self.line, self.col) < (other.line, other.col) + + def __le__(self, other): + return (self.line, self.col) <= (other.line, other.col) + + def __repr__(self): + return "(%i,%i)" % (self.line, self.col) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/__init__.py new file mode 100644 index 0000000..0128940 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/__init__.py @@ -0,0 +1 @@ +"""Code related to snippets.""" diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/__init__.py new file mode 100644 index 0000000..fb08801 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/__init__.py @@ -0,0 +1,4 @@ +"""In memory representation of snippet definitions.""" + +from UltiSnips.snippet.definition.ultisnips import UltiSnipsSnippetDefinition +from UltiSnips.snippet.definition.snipmate import SnipMateSnippetDefinition diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/_base.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/_base.py new file mode 100644 index 0000000..d89751b --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/_base.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Snippet representation after parsing.""" + +import re + +from UltiSnips import _vim +from UltiSnips.compatibility import as_unicode +from UltiSnips.indent_util import IndentUtil +from UltiSnips.text import escape +from UltiSnips.text_objects import SnippetInstance + +def _words_for_line(trigger, before, num_words=None): + """ Gets the final 'num_words' words from 'before'. + If num_words is None, then use the number of words in + 'trigger'. + """ + if not len(before): + return '' + + if num_words is None: + num_words = len(trigger.split()) + + word_list = before.split() + if len(word_list) <= num_words: + return before.strip() + else: + before_words = before + for i in range(-1, -(num_words + 1), -1): + left = before_words.rfind(word_list[i]) + before_words = before_words[:left] + return before[len(before_words):].strip() + +class SnippetDefinition(object): + """Represents a snippet as parsed from a file.""" + + _INDENT = re.compile(r"^[ \t]*") + _TABS = re.compile(r"^\t*") + + def __init__(self, priority, trigger, value, description, + options, globals, location): + self._priority = priority + self._trigger = as_unicode(trigger) + self._value = as_unicode(value) + self._description = as_unicode(description) + self._opts = options + self._matched = "" + self._last_re = None + self._globals = globals + self._location = location + + # Make sure that we actually match our trigger in case we are + # immediately expanded. + self.matches(self._trigger) + + def __repr__(self): + return "_SnippetDefinition(%r,%s,%s,%s)" % ( + self._priority, self._trigger, self._description, self._opts) + + def _re_match(self, trigger): + """ Test if a the current regex trigger matches + `trigger`. If so, set _last_re and _matched. + """ + for match in re.finditer(self._trigger, trigger): + if match.end() != len(trigger): + continue + else: + self._matched = trigger[match.start():match.end()] + + self._last_re = match + return match + return False + + def has_option(self, opt): + """ Check if the named option is set """ + return opt in self._opts + + @property + def description(self): + """Descriptive text for this snippet.""" + return ("(%s) %s" % (self._trigger, self._description)).strip() + + @property + def priority(self): + """The snippets priority, which defines which snippet will be preferred + over others with the same trigger.""" + return self._priority + + @property + def trigger(self): + """The trigger text for the snippet.""" + return self._trigger + + @property + def matched(self): + """The last text that matched this snippet in match() or + could_match().""" + return self._matched + + @property + def location(self): + """Where this snippet was defined.""" + return self._location + + def matches(self, trigger): + """Returns True if this snippet matches 'trigger'.""" + # If user supplies both "w" and "i", it should perhaps be an + # error, but if permitted it seems that "w" should take precedence + # (since matching at word boundary and within a word == matching at word + # boundary). + self._matched = "" + + # Don't expand on whitespace + if trigger and trigger.rstrip() != trigger: + return False + + words = _words_for_line(self._trigger, trigger) + + if "r" in self._opts: + match = self._re_match(trigger) + elif "w" in self._opts: + words_len = len(self._trigger) + words_prefix = words[:-words_len] + words_suffix = words[-words_len:] + match = (words_suffix == self._trigger) + if match and words_prefix: + # Require a word boundary between prefix and suffix. + boundary_chars = escape(words_prefix[-1:] + \ + words_suffix[:1], r'\"') + match = _vim.eval('"%s" =~# "\\\\v.<."' % boundary_chars) != '0' + elif "i" in self._opts: + match = words.endswith(self._trigger) + else: + match = (words == self._trigger) + + # By default, we match the whole trigger + if match and not self._matched: + self._matched = self._trigger + + # Ensure the match was on a word boundry if needed + if "b" in self._opts and match: + text_before = trigger.rstrip()[:-len(self._matched)] + if text_before.strip(" \t") != '': + self._matched = "" + return False + return match + + def could_match(self, trigger): + """Return True if this snippet could match the (partial) 'trigger'.""" + self._matched = "" + + # List all on whitespace. + if trigger and trigger[-1] in (" ", "\t"): + trigger = "" + if trigger and trigger.rstrip() is not trigger: + return False + + words = _words_for_line(self._trigger, trigger) + + if "r" in self._opts: + # Test for full match only + match = self._re_match(trigger) + elif "w" in self._opts: + # Trim non-empty prefix up to word boundary, if present. + qwords = escape(words, r'\"') + words_suffix = _vim.eval( + 'substitute("%s", "\\\\v^.+<(.+)", "\\\\1", "")' % qwords) + match = self._trigger.startswith(words_suffix) + self._matched = words_suffix + + # TODO: list_snippets() function cannot handle partial-trigger + # matches yet, so for now fail if we trimmed the prefix. + if words_suffix != words: + match = False + elif "i" in self._opts: + # TODO: It is hard to define when a inword snippet could match, + # therefore we check only for full-word trigger. + match = self._trigger.startswith(words) + else: + match = self._trigger.startswith(words) + + # By default, we match the words from the trigger + if match and not self._matched: + self._matched = words + + # Ensure the match was on a word boundry if needed + if "b" in self._opts and match: + text_before = trigger.rstrip()[:-len(self._matched)] + if text_before.strip(" \t") != '': + self._matched = "" + return False + + return match + + def instantiate(self, snippet_instance, initial_text, indent): + """Parses the content of this snippet and brings the corresponding text + objects alive inside of Vim.""" + raise NotImplementedError() + + def launch(self, text_before, visual_content, parent, start, end): + """Launch this snippet, overwriting the text 'start' to 'end' and + keeping the 'text_before' on the launch line. 'Parent' is the parent + snippet instance if any.""" + indent = self._INDENT.match(text_before).group(0) + lines = (self._value + "\n").splitlines() + ind_util = IndentUtil() + + # Replace leading tabs in the snippet definition via proper indenting + initial_text = [] + for line_num, line in enumerate(lines): + if "t" in self._opts: + tabs = 0 + else: + tabs = len(self._TABS.match(line).group(0)) + line_ind = ind_util.ntabs_to_proper_indent(tabs) + if line_num != 0: + line_ind = indent + line_ind + + initial_text.append(line_ind + line[tabs:]) + initial_text = '\n'.join(initial_text) + + snippet_instance = SnippetInstance( + self, parent, initial_text, start, end, visual_content, + last_re=self._last_re, globals=self._globals) + self.instantiate(snippet_instance, initial_text, indent) + + snippet_instance.update_textobjects() + return snippet_instance diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/snipmate.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/snipmate.py new file mode 100644 index 0000000..f257ce6 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/snipmate.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""A snipMate snippet after parsing.""" + +from UltiSnips.snippet.definition._base import SnippetDefinition +from UltiSnips.snippet.parsing.snipmate import parse_and_instantiate + +class SnipMateSnippetDefinition(SnippetDefinition): + """See module doc.""" + + SNIPMATE_SNIPPET_PRIORITY = -1000 + + def __init__(self, trigger, value, description, location): + SnippetDefinition.__init__(self, self.SNIPMATE_SNIPPET_PRIORITY, + trigger, value, description, "", {}, location) + + def instantiate(self, snippet_instance, initial_text, indent): + parse_and_instantiate(snippet_instance, initial_text, indent) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/ultisnips.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/ultisnips.py new file mode 100644 index 0000000..7c17a0d --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/definition/ultisnips.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""A UltiSnips snippet after parsing.""" + +from UltiSnips.snippet.definition._base import SnippetDefinition +from UltiSnips.snippet.parsing.ultisnips import parse_and_instantiate + +class UltiSnipsSnippetDefinition(SnippetDefinition): + """See module doc.""" + + def instantiate(self, snippet_instance, initial_text, indent): + return parse_and_instantiate(snippet_instance, initial_text, indent) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/__init__.py new file mode 100644 index 0000000..ea46beb --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/__init__.py @@ -0,0 +1 @@ +"""Code related to turning text into snippets.""" diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/_base.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/_base.py new file mode 100644 index 0000000..0b3d15d --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/_base.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Common functionality of the snippet parsing codes.""" + +from UltiSnips.position import Position +from UltiSnips.snippet.parsing._lexer import tokenize, TabStopToken +from UltiSnips.text_objects import TabStop + +def tokenize_snippet_text(snippet_instance, text, indent, + allowed_tokens_in_text, allowed_tokens_in_tabstops, + token_to_textobject): + """Turns 'text' into a stream of tokens and creates the text objects from + those tokens that are mentioned in 'token_to_textobject' assuming the + current 'indent'. The 'allowed_tokens_in_text' define which tokens will be + recognized in 'text' while 'allowed_tokens_in_tabstops' are the tokens that + will be recognized in TabStop placeholder text.""" + seen_ts = {} + all_tokens = [] + + def _do_parse(parent, text, allowed_tokens): + """Recursive function that actually creates the objects.""" + tokens = list(tokenize(text, indent, parent.start, allowed_tokens)) + for token in tokens: + all_tokens.append((parent, token)) + if isinstance(token, TabStopToken): + ts = TabStop(parent, token) + seen_ts[token.number] = ts + _do_parse(ts, token.initial_text, + allowed_tokens_in_tabstops) + else: + klass = token_to_textobject.get(token.__class__, None) + if klass is not None: + klass(parent, token) + _do_parse(snippet_instance, text, allowed_tokens_in_text) + return all_tokens, seen_ts + +def finalize(all_tokens, seen_ts, snippet_instance): + """Adds a tabstop 0 if non is in 'seen_ts' and brings the text of the + snippet instance into Vim.""" + if 0 not in seen_ts: + mark = all_tokens[-1][1].end # Last token is always EndOfText + m1 = Position(mark.line, mark.col) + TabStop(snippet_instance, 0, mark, m1) + snippet_instance.replace_initial_text() diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/_lexer.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/_lexer.py new file mode 100644 index 0000000..1c5794f --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/_lexer.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python +# encoding: utf-8 + +""" +Not really a lexer in the classical sense, but code to convert snippet +definitions into logical units called Tokens. +""" + +import string +import re + +from UltiSnips.compatibility import as_unicode +from UltiSnips.position import Position +from UltiSnips.text import unescape + +class _TextIterator(object): + """Helper class to make iterating over text easier.""" + + def __init__(self, text, offset): + self._text = as_unicode(text) + self._line = offset.line + self._col = offset.col + + self._idx = 0 + + def __iter__(self): + """Iterator interface.""" + return self + + def __next__(self): + """Returns the next character.""" + if self._idx >= len(self._text): + raise StopIteration + + rv = self._text[self._idx] + if self._text[self._idx] in ('\n', '\r\n'): + self._line += 1 + self._col = 0 + else: + self._col += 1 + self._idx += 1 + return rv + next = __next__ # for python2 + + def peek(self, count=1): + """Returns the next 'count' characters without advancing the stream.""" + if count > 1: # This might return '' if nothing is found + return self._text[self._idx:self._idx + count] + try: + return self._text[self._idx] + except IndexError: + return None + + @property + def pos(self): + """Current position in the text.""" + return Position(self._line, self._col) + +def _parse_number(stream): + """ + Expects the stream to contain a number next, returns the number + without consuming any more bytes + """ + rv = "" + while stream.peek() and stream.peek() in string.digits: + rv += next(stream) + + return int(rv) + +def _parse_till_closing_brace(stream): + """ + Returns all chars till a non-escaped } is found. Other + non escaped { are taken into account and skipped over. + + Will also consume the closing }, but not return it + """ + rv = "" + in_braces = 1 + while True: + if EscapeCharToken.starts_here(stream, '{}'): + rv += next(stream) + next(stream) + else: + char = next(stream) + if char == '{': + in_braces += 1 + elif char == '}': + in_braces -= 1 + if in_braces == 0: + break + rv += char + return rv + +def _parse_till_unescaped_char(stream, chars): + """ + Returns all chars till a non-escaped char is found. + + Will also consume the closing char, but and return it as second + return value + """ + rv = "" + while True: + escaped = False + for char in chars: + if EscapeCharToken.starts_here(stream, char): + rv += next(stream) + next(stream) + escaped = True + if not escaped: + char = next(stream) + if char in chars: + break + rv += char + return rv, char + +class Token(object): + """Represents a Token as parsed from a snippet definition.""" + + def __init__(self, gen, indent): + self.initial_text = as_unicode("") + self.start = gen.pos + self._parse(gen, indent) + self.end = gen.pos + + def _parse(self, stream, indent): + """Parses the token from 'stream' with the current 'indent'.""" + pass # Does nothing + +class TabStopToken(Token): + """${1:blub}""" + CHECK = re.compile(r'^\${\d+[:}]') + + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return cls.CHECK.match(stream.peek(10)) is not None + + def _parse(self, stream, indent): + next(stream) # $ + next(stream) # { + + self.number = _parse_number(stream) + + if stream.peek() == ":": + next(stream) + self.initial_text = _parse_till_closing_brace(stream) + + def __repr__(self): + return "TabStopToken(%r,%r,%r,%r)" % ( + self.start, self.end, self.number, self.initial_text + ) + +class VisualToken(Token): + """${VISUAL}""" + CHECK = re.compile(r"^\${VISUAL[:}/]") + + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return cls.CHECK.match(stream.peek(10)) is not None + + def _parse(self, stream, indent): + for _ in range(8): # ${VISUAL + next(stream) + + if stream.peek() == ":": + next(stream) + self.alternative_text, char = _parse_till_unescaped_char(stream, '/}') + self.alternative_text = unescape(self.alternative_text) + + if char == '/': # Transformation going on + try: + self.search = _parse_till_unescaped_char(stream, '/')[0] + self.replace = _parse_till_unescaped_char(stream, '/')[0] + self.options = _parse_till_closing_brace(stream) + except StopIteration: + raise RuntimeError( + "Invalid ${VISUAL} transformation! Forgot to escape a '/'?") + else: + self.search = None + self.replace = None + self.options = None + + def __repr__(self): + return "VisualToken(%r,%r)" % ( + self.start, self.end + ) + +class TransformationToken(Token): + """${1/match/replace/options}""" + + CHECK = re.compile(r'^\${\d+\/') + + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return cls.CHECK.match(stream.peek(10)) is not None + + def _parse(self, stream, indent): + next(stream) # $ + next(stream) # { + + self.number = _parse_number(stream) + + next(stream) # / + + self.search = _parse_till_unescaped_char(stream, '/')[0] + self.replace = _parse_till_unescaped_char(stream, '/')[0] + self.options = _parse_till_closing_brace(stream) + + def __repr__(self): + return "TransformationToken(%r,%r,%r,%r,%r)" % ( + self.start, self.end, self.number, self.search, self.replace + ) + +class MirrorToken(Token): + """$1""" + CHECK = re.compile(r'^\$\d+') + + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return cls.CHECK.match(stream.peek(10)) is not None + + def _parse(self, stream, indent): + next(stream) # $ + self.number = _parse_number(stream) + + def __repr__(self): + return "MirrorToken(%r,%r,%r)" % ( + self.start, self.end, self.number + ) + +class EscapeCharToken(Token): + """\\n""" + @classmethod + def starts_here(cls, stream, chars=r'{}\$`'): + """Returns true if this token starts at the current position in + 'stream'.""" + cs = stream.peek(2) + if len(cs) == 2 and cs[0] == '\\' and cs[1] in chars: + return True + + def _parse(self, stream, indent): + next(stream) # \ + self.initial_text = next(stream) + + def __repr__(self): + return "EscapeCharToken(%r,%r,%r)" % ( + self.start, self.end, self.initial_text + ) + +class ShellCodeToken(Token): + """`echo "hi"`""" + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return stream.peek(1) == '`' + + def _parse(self, stream, indent): + next(stream) # ` + self.code = _parse_till_unescaped_char(stream, '`')[0] + + def __repr__(self): + return "ShellCodeToken(%r,%r,%r)" % ( + self.start, self.end, self.code + ) + +class PythonCodeToken(Token): + """`!p snip.rv = "Hi"`""" + CHECK = re.compile(r'^`!p\s') + + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return cls.CHECK.match(stream.peek(4)) is not None + + def _parse(self, stream, indent): + for _ in range(3): + next(stream) # `!p + if stream.peek() in '\t ': + next(stream) + + code = _parse_till_unescaped_char(stream, '`')[0] + + # Strip the indent if any + if len(indent): + lines = code.splitlines() + self.code = lines[0] + '\n' + self.code += '\n'.join([l[len(indent):] + for l in lines[1:]]) + else: + self.code = code + self.indent = indent + + def __repr__(self): + return "PythonCodeToken(%r,%r,%r)" % ( + self.start, self.end, self.code + ) + +class VimLCodeToken(Token): + """`!v g:hi`""" + CHECK = re.compile(r'^`!v\s') + + @classmethod + def starts_here(cls, stream): + """Returns true if this token starts at the current position in + 'stream'.""" + return cls.CHECK.match(stream.peek(4)) is not None + + def _parse(self, stream, indent): + for _ in range(4): + next(stream) # `!v + self.code = _parse_till_unescaped_char(stream, '`')[0] + + def __repr__(self): + return "VimLCodeToken(%r,%r,%r)" % ( + self.start, self.end, self.code + ) + +class EndOfTextToken(Token): + """Appears at the end of the text.""" + def __repr__(self): + return "EndOfText(%r)" % self.end + +def tokenize(text, indent, offset, allowed_tokens): + """Returns an iterator of tokens of 'text'['offset':] which is assumed to + have 'indent' as the whitespace of the begging of the lines. Only + 'allowed_tokens' are considered to be valid tokens.""" + stream = _TextIterator(text, offset) + try: + while True: + done_something = False + for token in allowed_tokens: + if token.starts_here(stream): + yield token(stream, indent) + done_something = True + break + if not done_something: + next(stream) + except StopIteration: + yield EndOfTextToken(stream, indent) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/snipmate.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/snipmate.py new file mode 100644 index 0000000..cdccfd9 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/snipmate.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Parses a snipMate snippet definition and launches it into Vim.""" + +from UltiSnips.snippet.parsing._base import tokenize_snippet_text, finalize +from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \ + VisualToken, TabStopToken, MirrorToken, ShellCodeToken +from UltiSnips.text_objects import EscapedChar, Mirror, VimLCode, Visual + +_TOKEN_TO_TEXTOBJECT = { + EscapeCharToken: EscapedChar, + VisualToken: Visual, + ShellCodeToken: VimLCode, # `` is VimL in snipMate +} + +__ALLOWED_TOKENS = [ + EscapeCharToken, VisualToken, TabStopToken, MirrorToken, ShellCodeToken +] + +__ALLOWED_TOKENS_IN_TABSTOPS = [ + EscapeCharToken, VisualToken, MirrorToken, ShellCodeToken +] + +def _create_mirrors(all_tokens, seen_ts): + """Now that all tabstops are known, we can create mirrors.""" + for parent, token in all_tokens: + if isinstance(token, MirrorToken): + Mirror(parent, seen_ts[token.number], token) + +def parse_and_instantiate(parent_to, text, indent): + """Parses a snippet definition in snipMate format from 'text' assuming the + current 'indent'. Will instantiate all the objects and link them as + children to parent_to. Will also put the initial text into Vim.""" + all_tokens, seen_ts = tokenize_snippet_text(parent_to, text, indent, + __ALLOWED_TOKENS, __ALLOWED_TOKENS_IN_TABSTOPS, + _TOKEN_TO_TEXTOBJECT) + _create_mirrors(all_tokens, seen_ts) + finalize(all_tokens, seen_ts, parent_to) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/ultisnips.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/ultisnips.py new file mode 100644 index 0000000..4417813 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/parsing/ultisnips.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Parses a UltiSnips snippet definition and launches it into Vim.""" + +from UltiSnips.snippet.parsing._base import tokenize_snippet_text, finalize +from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \ + VisualToken, TransformationToken, TabStopToken, MirrorToken, \ + PythonCodeToken, VimLCodeToken, ShellCodeToken +from UltiSnips.text_objects import EscapedChar, Mirror, PythonCode, \ + ShellCode, TabStop, Transformation, VimLCode, Visual + +_TOKEN_TO_TEXTOBJECT = { + EscapeCharToken: EscapedChar, + VisualToken: Visual, + ShellCodeToken: ShellCode, + PythonCodeToken: PythonCode, + VimLCodeToken: VimLCode, +} + +__ALLOWED_TOKENS = [ + EscapeCharToken, VisualToken, TransformationToken, TabStopToken, + MirrorToken, PythonCodeToken, VimLCodeToken, ShellCodeToken +] + +def _resolve_ambiguity(all_tokens, seen_ts): + """$1 could be a Mirror or a TabStop. This figures this out.""" + for parent, token in all_tokens: + if isinstance(token, MirrorToken): + if token.number not in seen_ts: + seen_ts[token.number] = TabStop(parent, token) + else: + Mirror(parent, seen_ts[token.number], token) + +def _create_transformations(all_tokens, seen_ts): + """Create the objects that need to know about tabstops.""" + for parent, token in all_tokens: + if isinstance(token, TransformationToken): + if token.number not in seen_ts: + raise RuntimeError( + "Tabstop %i is not known but is used by a Transformation" + % token.number) + Transformation(parent, seen_ts[token.number], token) + + +def parse_and_instantiate(parent_to, text, indent): + """Parses a snippet definition in UltiSnips format from 'text' assuming the + current 'indent'. Will instantiate all the objects and link them as + children to parent_to. Will also put the initial text into Vim.""" + all_tokens, seen_ts = tokenize_snippet_text(parent_to, text, indent, + __ALLOWED_TOKENS, __ALLOWED_TOKENS, _TOKEN_TO_TEXTOBJECT) + _resolve_ambiguity(all_tokens, seen_ts) + _create_transformations(all_tokens, seen_ts) + finalize(all_tokens, seen_ts, parent_to) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/__init__.py new file mode 100644 index 0000000..08c20ac --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/__init__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Sources of snippet definitions.""" + +from UltiSnips.snippet.source._base import SnippetSource +from UltiSnips.snippet.source.added import AddedSnippetsSource +from UltiSnips.snippet.source.file.snipmate import SnipMateFileSource +from UltiSnips.snippet.source.file.ultisnips import UltiSnipsFileSource, \ + find_all_snippet_files, find_snippet_files diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/_base.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/_base.py new file mode 100644 index 0000000..bca5079 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/_base.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Base class for snippet sources.""" + +from collections import defaultdict + +from UltiSnips.snippet.source._snippet_dictionary import SnippetDictionary + +class SnippetSource(object): + """See module docstring.""" + + def __init__(self): + self._snippets = defaultdict(SnippetDictionary) + self._extends = defaultdict(set) + + def ensure(self, filetypes): + """Update/reload the snippets in the source when needed. It makes sure + that the snippets are not outdated. + """ + pass + + def _get_existing_deep_extends(self, base_filetypes): + """Helper for get all existing filetypes extended by base + filetypes. + """ + deep_extends = self.get_deep_extends(base_filetypes) + return [ft for ft in deep_extends if ft in self._snippets] + + def get_snippets(self, filetypes, before, possible): + """Returns the snippets for all 'filetypes' (in order) and their parents + matching the text 'before'. If 'possible' is true, a partial match is + enough. Base classes can override this method to provide means of + creating snippets on the fly. + + Returns a list of SnippetDefinition s. + """ + result = [] + for ft in self._get_existing_deep_extends(filetypes): + snips = self._snippets[ft] + result.extend(snips.get_matching_snippets(before, possible)) + return result + + def get_clear_priority(self, filetypes): + """Get maximum clearsnippets priority without arguments for specified + filetypes, if any. It returns None if there are no clearsnippets. + """ + pri = None + for ft in self._get_existing_deep_extends(filetypes): + snippets = self._snippets[ft] + if pri is None or snippets._clear_priority > pri: + pri = snippets._clear_priority + return pri + + def get_cleared(self, filetypes): + """Get a set of cleared snippets marked by clearsnippets with arguments + for specified filetypes. + """ + cleared = {} + for ft in self._get_existing_deep_extends(filetypes): + snippets = self._snippets[ft] + for key, value in snippets._cleared.items(): + if key not in cleared or value > cleared[key]: + cleared[key] = value + return cleared + + def update_extends(self, child_ft, parent_fts): + """Update the extending relation by given child filetype and + its parent filetypes. + """ + self._extends[child_ft].update(parent_fts) + + def get_deep_extends(self, base_filetypes): + """Get a list of filetypes that is either directed or indirected + extended by given base filetypes. Note that the returned list + include the root filetype itself. + """ + seen = set(base_filetypes) + todo_fts = list(set(base_filetypes)) + while todo_fts: + todo_ft = todo_fts.pop() + unseen_extends = set(ft for ft in self._extends[todo_ft] if ft not in seen) + seen.update(unseen_extends) + todo_fts.extend(unseen_extends) + return seen diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/_snippet_dictionary.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/_snippet_dictionary.py new file mode 100644 index 0000000..5b23a32 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/_snippet_dictionary.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Implements a container for parsed snippets.""" + +class SnippetDictionary(object): + """See module docstring.""" + + def __init__(self): + self._snippets = [] + self._cleared = {} + self._clear_priority = None + + def add_snippet(self, snippet): + """Add 'snippet' to this dictionary.""" + self._snippets.append(snippet) + + def get_matching_snippets(self, trigger, potentially): + """Returns all snippets matching the given trigger. If 'potentially' is + true, returns all that could_match().""" + all_snippets = self._snippets + if not potentially: + return [s for s in all_snippets if s.matches(trigger)] + else: + return [s for s in all_snippets if s.could_match(trigger)] + + def clear_snippets(self, priority, triggers): + """Clear the snippets by mark them as cleared. If trigger is + None, it updates the value of clear priority instead.""" + if not triggers: + if self._clear_priority is None or priority > self._clear_priority: + self._clear_priority = priority + else: + for trigger in triggers: + if (trigger not in self._cleared or + priority > self._cleared[trigger]): + self._cleared[trigger] = priority diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/added.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/added.py new file mode 100644 index 0000000..a6a144d --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/added.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Handles manually added snippets UltiSnips_Manager.add_snippet().""" + +from UltiSnips.snippet.source._base import SnippetSource + +class AddedSnippetsSource(SnippetSource): + """See module docstring.""" + + def add_snippet(self, ft, snippet): + """Adds the given 'snippet' for 'ft'.""" + self._snippets[ft].add_snippet(snippet) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/__init__.py new file mode 100644 index 0000000..6abf472 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/__init__.py @@ -0,0 +1 @@ +"""Snippet sources that are file based.""" diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_base.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_base.py new file mode 100644 index 0000000..20f67e8 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_base.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Code to provide access to UltiSnips files from disk.""" + +from collections import defaultdict +import hashlib +import os + +from UltiSnips import _vim +from UltiSnips import compatibility +from UltiSnips.snippet.source._base import SnippetSource + +def _hash_file(path): + """Returns a hashdigest of 'path'""" + if not os.path.isfile(path): + return False + return hashlib.sha1(open(path, "rb").read()).hexdigest() + +class SnippetSyntaxError(RuntimeError): + """Thrown when a syntax error is found in a file.""" + def __init__(self, filename, line_index, msg): + RuntimeError.__init__(self, "%s in %s:%d" % ( + msg, filename, line_index)) + +class SnippetFileSource(SnippetSource): + """Base class that abstracts away 'extends' info and file hashes.""" + + def __init__(self): + SnippetSource.__init__(self) + self._files_for_ft = defaultdict(set) + self._file_hashes = defaultdict(lambda: None) + + def ensure(self, filetypes): + for ft in self.get_deep_extends(filetypes): + if self._needs_update(ft): + self._load_snippets_for(ft) + + def _get_all_snippet_files_for(self, ft): + """Returns a set of all files that define snippets for 'ft'.""" + raise NotImplementedError() + + def _parse_snippet_file(self, filedata, filename): + """Parses 'filedata' as a snippet file and yields events.""" + raise NotImplementedError() + + def _needs_update(self, ft): + """Returns true if any files for 'ft' have changed and must be + reloaded.""" + existing_files = self._get_all_snippet_files_for(ft) + if existing_files != self._files_for_ft[ft]: + self._files_for_ft[ft] = existing_files + return True + + for filename in self._files_for_ft[ft]: + if _hash_file(filename) != self._file_hashes[filename]: + return True + + return False + + def _load_snippets_for(self, ft): + """Load all snippets for the given 'ft'.""" + if ft in self._snippets: + del self._snippets[ft] + del self._extends[ft] + for fn in self._files_for_ft[ft]: + self._parse_snippets(ft, fn) + # Now load for the parents + for parent_ft in self.get_deep_extends([ft]): + if parent_ft != ft and self._needs_update(parent_ft): + self._load_snippets_for(parent_ft) + + def _parse_snippets(self, ft, filename): + """Parse the 'filename' for the given 'ft' and watch it for changes in + the future.""" + self._file_hashes[filename] = _hash_file(filename) + file_data = compatibility.open_ascii_file(filename, "r").read() + for event, data in self._parse_snippet_file(file_data, filename): + if event == "error": + msg, line_index = data + filename = _vim.eval("""fnamemodify(%s, ":~:.")""" % + _vim.escape(filename)) + raise SnippetSyntaxError(filename, line_index, msg) + elif event == "clearsnippets": + priority, triggers = data + self._snippets[ft].clear_snippets(priority, triggers) + elif event == "extends": + # TODO(sirver): extends information is more global + # than one snippet source. + filetypes, = data + self.update_extends(ft, filetypes) + elif event == "snippet": + snippet, = data + self._snippets[ft].add_snippet(snippet) + else: + assert False, "Unhandled %s: %r" % (event, data) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_common.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_common.py new file mode 100644 index 0000000..4b8097a --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/_common.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Common code for snipMate and UltiSnips snippet files.""" + +def handle_extends(tail, line_index): + """Handles an extends line in a snippet.""" + if tail: + return "extends", ([p.strip() for p in tail.split(',')],) + else: + return "error", ("'extends' without file types", line_index) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/snipmate.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/snipmate.py new file mode 100644 index 0000000..12e4ea0 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/snipmate.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Parses snipMate files.""" + +import os +import glob + +from UltiSnips import _vim +from UltiSnips.snippet.definition import SnipMateSnippetDefinition +from UltiSnips.snippet.source.file._base import SnippetFileSource +from UltiSnips.snippet.source.file._common import handle_extends +from UltiSnips.text import LineIterator, head_tail + +def _splitall(path): + """Split 'path' into all its components.""" + # From http://my.safaribooksonline.com/book/programming/ + # python/0596001673/files/pythoncook-chp-4-sect-16 + allparts = [] + while 1: + parts = os.path.split(path) + if parts[0] == path: # sentinel for absolute paths + allparts.insert(0, parts[0]) + break + elif parts[1] == path: # sentinel for relative paths + allparts.insert(0, parts[1]) + break + else: + path = parts[0] + allparts.insert(0, parts[1]) + return allparts + +def snipmate_files_for(ft): + """Returns all snipMate files we need to look at for 'ft'.""" + if ft == "all": + ft = "_" + patterns = [ + "%s.snippets" % ft, + os.path.join(ft, "*.snippets"), + os.path.join(ft, "*.snippet"), + os.path.join(ft, "*/*.snippet"), + ] + ret = set() + for rtp in _vim.eval("&runtimepath").split(','): + path = os.path.realpath(os.path.expanduser( + os.path.join(rtp, "snippets"))) + for pattern in patterns: + for fn in glob.glob(os.path.join(path, pattern)): + ret.add(fn) + return ret + +def _parse_snippet_file(content, full_filename): + """Parses 'content' assuming it is a .snippet file and yields events.""" + filename = full_filename[:-len(".snippet")] # strip extension + segments = _splitall(filename) + segments = segments[segments.index("snippets")+1:] + assert len(segments) in (2, 3) + + trigger = segments[1] + description = segments[2] if 2 < len(segments) else "" + + # Chomp \n if any. + if content and content.endswith(os.linesep): + content = content[:-len(os.linesep)] + yield "snippet", (SnipMateSnippetDefinition(trigger, content, + description, full_filename),) + +def _parse_snippet(line, lines, filename): + """Parse a snippet defintions.""" + start_line_index = lines.line_index + trigger, description = head_tail(line[len("snippet"):].lstrip()) + content = "" + while True: + next_line = lines.peek() + if next_line is None: + break + if next_line.strip() and not next_line.startswith('\t'): + break + line = next(lines) + if line[0] == '\t': + line = line[1:] + content += line + content = content[:-1] # Chomp the last newline + return "snippet", (SnipMateSnippetDefinition( + trigger, content, description, "%s:%i" % (filename, start_line_index)),) + +def _parse_snippets_file(data, filename): + """Parse 'data' assuming it is a .snippets file. Yields events in the + file.""" + lines = LineIterator(data) + for line in lines: + if not line.strip(): + continue + + head, tail = head_tail(line) + if head == "extends": + yield handle_extends(tail, lines.line_index) + elif head in "snippet": + snippet = _parse_snippet(line, lines, filename) + if snippet is not None: + yield snippet + elif head and not head.startswith('#'): + yield "error", ("Invalid line %r" % line.rstrip(), lines.line_index) + +class SnipMateFileSource(SnippetFileSource): + """Manages all snipMate snippet definitions found in rtp.""" + def _get_all_snippet_files_for(self, ft): + return snipmate_files_for(ft) + + def _parse_snippet_file(self, filedata, filename): + if filename.lower().endswith("snippet"): + for event, data in _parse_snippet_file(filedata, filename): + yield event, data + else: + for event, data in _parse_snippets_file(filedata, filename): + yield event, data diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/ultisnips.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/ultisnips.py new file mode 100644 index 0000000..81878a0 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet/source/file/ultisnips.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Parsing of snippet files.""" + +from collections import defaultdict +import glob +import os + +from UltiSnips import _vim +from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition +from UltiSnips.snippet.source.file._base import SnippetFileSource +from UltiSnips.snippet.source.file._common import handle_extends +from UltiSnips.text import LineIterator, head_tail + +def find_snippet_files(ft, directory): + """Returns all matching snippet files for 'ft' in 'directory'.""" + patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")] + ret = set() + directory = os.path.expanduser(directory) + for pattern in patterns: + for fn in glob.glob(os.path.join(directory, pattern % ft)): + ret.add(os.path.realpath(fn)) + return ret + +def find_all_snippet_files(ft): + """Returns all snippet files matching 'ft' in the given runtime path + directory.""" + if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1": + snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories") + else: + snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories") + + patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")] + ret = set() + for rtp in _vim.eval("&runtimepath").split(','): + for snippet_dir in snippet_dirs: + if snippet_dir == "snippets": + raise RuntimeError( + "You have 'snippets' in UltiSnipsSnippetDirectories. This " + "directory is reserved for snipMate snippets. Use another " + "directory for UltiSnips snippets.") + pth = os.path.realpath(os.path.expanduser( + os.path.join(rtp, snippet_dir))) + for pattern in patterns: + for fn in glob.glob(os.path.join(pth, pattern % ft)): + ret.add(fn) + return ret + +def _handle_snippet_or_global(filename, line, lines, python_globals, priority): + """Parses the snippet that begins at the current line.""" + start_line_index = lines.line_index + descr = "" + opts = "" + + # Ensure this is a snippet + snip = line.split()[0] + + # Get and strip options if they exist + remain = line[len(snip):].strip() + words = remain.split() + if len(words) > 2: + # second to last word ends with a quote + if '"' not in words[-1] and words[-2][-1] == '"': + opts = words[-1] + remain = remain[:-len(opts) - 1].rstrip() + + # Get and strip description if it exists + remain = remain.strip() + if len(remain.split()) > 1 and remain[-1] == '"': + left = remain[:-1].rfind('"') + if left != -1 and left != 0: + descr, remain = remain[left:], remain[:left] + + # The rest is the trigger + trig = remain.strip() + if len(trig.split()) > 1 or "r" in opts: + if trig[0] != trig[-1]: + return "error", ("Invalid multiword trigger: '%s'" % trig, + lines.line_index) + trig = trig[1:-1] + end = "end" + snip + content = "" + + found_end = False + for line in lines: + if line.rstrip() == end: + content = content[:-1] # Chomp the last newline + found_end = True + break + content += line + + if not found_end: + return "error", ("Missing 'endsnippet' for %r" % trig, lines.line_index) + + if snip == "global": + python_globals[trig].append(content) + elif snip == "snippet": + return "snippet", (UltiSnipsSnippetDefinition(priority, trig, content, + descr, opts, python_globals, + "%s:%i" % (filename, start_line_index)),) + else: + return "error", ("Invalid snippet type: '%s'" % snip, lines.line_index) + +def _parse_snippets_file(data, filename): + """Parse 'data' assuming it is a snippet file. Yields events in the + file.""" + + python_globals = defaultdict(list) + lines = LineIterator(data) + current_priority = 0 + for line in lines: + if not line.strip(): + continue + + head, tail = head_tail(line) + if head in ("snippet", "global"): + snippet = _handle_snippet_or_global(filename, line, lines, + python_globals, current_priority) + if snippet is not None: + yield snippet + elif head == "extends": + yield handle_extends(tail, lines.line_index) + elif head == "clearsnippets": + yield "clearsnippets", (current_priority, tail.split()) + elif head == "priority": + try: + current_priority = int(tail.split()[0]) + except (ValueError, IndexError): + yield "error", ("Invalid priority %r" % tail, lines.line_index) + elif head and not head.startswith('#'): + yield "error", ("Invalid line %r" % line.rstrip(), lines.line_index) + +class UltiSnipsFileSource(SnippetFileSource): + """Manages all snippets definitions found in rtp for ultisnips.""" + + def _get_all_snippet_files_for(self, ft): + return find_all_snippet_files(ft) + + def _parse_snippet_file(self, filedata, filename): + for event, data in _parse_snippets_file(filedata, filename): + yield event, data diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py new file mode 100644 index 0000000..d33c8ab --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/snippet_manager.py @@ -0,0 +1,617 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Contains the SnippetManager facade used by all Vim Functions.""" + +from collections import defaultdict +from functools import wraps +import os +import platform +import traceback + +from UltiSnips import _vim +from UltiSnips._diff import diff, guess_edit +from UltiSnips.compatibility import as_unicode +from UltiSnips.position import Position +from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition +from UltiSnips.snippet.source import UltiSnipsFileSource, SnipMateFileSource, \ + find_all_snippet_files, find_snippet_files, AddedSnippetsSource +from UltiSnips.text import escape +from UltiSnips.vim_state import VimState, VisualContentPreserver + +def _ask_user(a, formatted): + """Asks the user using inputlist() and returns the selected element or + None.""" + try: + rv = _vim.eval("inputlist(%s)" % _vim.escape(formatted)) + if rv is None or rv == '0': + return None + rv = int(rv) + if rv > len(a): + rv = len(a) + return a[rv-1] + except _vim.error: + # Likely "invalid expression", but might be translated. We have no way + # of knowing the exact error, therefore, we ignore all errors silently. + return None + except KeyboardInterrupt: + return None + +def _ask_snippets(snippets): + """ Given a list of snippets, ask the user which one they + want to use, and return it. + """ + display = [as_unicode("%i: %s (%s)") % (i+1, escape(s.description, '\\'), + escape(s.location, '\\')) for i, s in enumerate(snippets)] + return _ask_user(snippets, display) + +def err_to_scratch_buffer(func): + """Decorator that will catch any Exception that 'func' throws and displays + it in a new Vim scratch buffer.""" + @wraps(func) + def wrapper(self, *args, **kwds): + try: + return func(self, *args, **kwds) + except: # pylint: disable=bare-except + msg = \ +"""An error occured. This is either a bug in UltiSnips or a bug in a +snippet definition. If you think this is a bug, please report it to +https://github.com/SirVer/ultisnips/issues/new. + +Following is the full stack trace: +""" + msg += traceback.format_exc() + # Vim sends no WinLeave msg here. + self._leaving_buffer() # pylint:disable=protected-access + _vim.new_scratch_buffer(msg) + return wrapper + + +# TODO(sirver): This class is still too long. It should only contain public +# facing methods, most of the private methods should be moved outside of it. +class SnippetManager(object): + """The main entry point for all UltiSnips functionality. All Vim functions + call methods in this class.""" + + def __init__(self, expand_trigger, forward_trigger, backward_trigger): + self.expand_trigger = expand_trigger + self.forward_trigger = forward_trigger + self.backward_trigger = backward_trigger + self._inner_mappings_in_place = False + self._supertab_keys = None + + self._csnippets = [] + self._buffer_filetypes = defaultdict(lambda: ['all']) + + self._vstate = VimState() + self._visual_content = VisualContentPreserver() + + self._snippet_sources = [] + + self._added_snippets_source = AddedSnippetsSource() + self.register_snippet_source("ultisnips_files", UltiSnipsFileSource()) + self.register_snippet_source("added", self._added_snippets_source) + self.register_snippet_source("snipmate_files", SnipMateFileSource()) + + self._reinit() + + @err_to_scratch_buffer + def jump_forwards(self): + """Jumps to the next tabstop.""" + _vim.command("let g:ulti_jump_forwards_res = 1") + if not self._jump(): + _vim.command("let g:ulti_jump_forwards_res = 0") + return self._handle_failure(self.forward_trigger) + + @err_to_scratch_buffer + def jump_backwards(self): + """Jumps to the previous tabstop.""" + _vim.command("let g:ulti_jump_backwards_res = 1") + if not self._jump(True): + _vim.command("let g:ulti_jump_backwards_res = 0") + return self._handle_failure(self.backward_trigger) + + @err_to_scratch_buffer + def expand(self): + """Try to expand a snippet at the current position.""" + _vim.command("let g:ulti_expand_res = 1") + if not self._try_expand(): + _vim.command("let g:ulti_expand_res = 0") + self._handle_failure(self.expand_trigger) + + @err_to_scratch_buffer + def expand_or_jump(self): + """ + This function is used for people who wants to have the same trigger for + expansion and forward jumping. It first tries to expand a snippet, if + this fails, it tries to jump forward. + """ + _vim.command('let g:ulti_expand_or_jump_res = 1') + rv = self._try_expand() + if not rv: + _vim.command('let g:ulti_expand_or_jump_res = 2') + rv = self._jump() + if not rv: + _vim.command('let g:ulti_expand_or_jump_res = 0') + self._handle_failure(self.expand_trigger) + + @err_to_scratch_buffer + def snippets_in_current_scope(self): + """Returns the snippets that could be expanded to Vim as a global + variable.""" + before = _vim.buf.line_till_cursor + snippets = self._snips(before, True) + + # Sort snippets alphabetically + snippets.sort(key=lambda x: x.trigger) + for snip in snippets: + description = snip.description[snip.description.find(snip.trigger) + + len(snip.trigger) + 2:] + + key = as_unicode(snip.trigger) + description = as_unicode(description) + + # remove surrounding "" or '' in snippet description if it exists + if len(description) > 2: + if (description[0] == description[-1] and + description[0] in "'\""): + description = description[1:-1] + + _vim.command(as_unicode( + "let g:current_ulti_dict['{key}'] = '{val}'").format( + key=key.replace("'", "''"), + val=description.replace("'", "''"))) + + @err_to_scratch_buffer + def list_snippets(self): + """Shows the snippets that could be expanded to the User and let her + select one.""" + before = _vim.buf.line_till_cursor + snippets = self._snips(before, True) + + if len(snippets) == 0: + self._handle_failure(self.backward_trigger) + return True + + # Sort snippets alphabetically + snippets.sort(key=lambda x: x.trigger) + + if not snippets: + return True + + snippet = _ask_snippets(snippets) + if not snippet: + return True + + self._do_snippet(snippet, before) + + return True + + @err_to_scratch_buffer + def add_snippet(self, trigger, value, description, + options, ft="all", priority=0): + """Add a snippet to the list of known snippets of the given 'ft'.""" + self._added_snippets_source.add_snippet(ft, + UltiSnipsSnippetDefinition(priority, trigger, value, + description, options, {}, "added")) + + @err_to_scratch_buffer + def expand_anon(self, value, trigger="", description="", options=""): + """Expand an anonymous snippet right here.""" + before = _vim.buf.line_till_cursor + snip = UltiSnipsSnippetDefinition(0, trigger, value, description, + options, {}, "") + + if not trigger or snip.matches(before): + self._do_snippet(snip, before) + return True + else: + return False + + def register_snippet_source(self, name, snippet_source): + """Registers a new 'snippet_source' with the given 'name'. The given + class must be an instance of SnippetSource. This source will be queried + for snippets.""" + self._snippet_sources.append((name, snippet_source)) + + def unregister_snippet_source(self, name): + """Unregister the source with the given 'name'. Does nothing if it is + not registered.""" + for index, (source_name, _) in enumerate(self._snippet_sources): + if name == source_name: + self._snippet_sources = self._snippet_sources[:index] + \ + self._snippet_sources[index+1:] + break + + def reset_buffer_filetypes(self): + """Reset the filetypes for the current buffer.""" + if _vim.buf.number in self._buffer_filetypes: + del self._buffer_filetypes[_vim.buf.number] + + def add_buffer_filetypes(self, ft): + """Checks for changes in the list of snippet files or the contents of + the snippet files and reloads them if necessary. """ + buf_fts = self._buffer_filetypes[_vim.buf.number] + idx = -1 + for ft in ft.split("."): + ft = ft.strip() + if not ft: + continue + try: + idx = buf_fts.index(ft) + except ValueError: + self._buffer_filetypes[_vim.buf.number].insert(idx + 1, ft) + idx += 1 + + @err_to_scratch_buffer + def _cursor_moved(self): + """Called whenever the cursor moved.""" + if not self._csnippets and self._inner_mappings_in_place: + self._unmap_inner_keys() + self._vstate.remember_position() + if _vim.eval("mode()") not in 'in': + return + + if self._ignore_movements: + self._ignore_movements = False + return + + if self._csnippets: + cstart = self._csnippets[0].start.line + cend = self._csnippets[0].end.line + \ + self._vstate.diff_in_buffer_length + ct = _vim.buf[cstart:cend + 1] + lt = self._vstate.remembered_buffer + pos = _vim.buf.cursor + + lt_span = [0, len(lt)] + ct_span = [0, len(ct)] + initial_line = cstart + + # Cut down on lines searched for changes. Start from behind and + # remove all equal lines. Then do the same from the front. + if lt and ct: + while (lt[lt_span[1]-1] == ct[ct_span[1]-1] and + self._vstate.ppos.line < initial_line + lt_span[1]-1 and + pos.line < initial_line + ct_span[1]-1 and + (lt_span[0] < lt_span[1]) and + (ct_span[0] < ct_span[1])): + ct_span[1] -= 1 + lt_span[1] -= 1 + while (lt_span[0] < lt_span[1] and + ct_span[0] < ct_span[1] and + lt[lt_span[0]] == ct[ct_span[0]] and + self._vstate.ppos.line >= initial_line and + pos.line >= initial_line): + ct_span[0] += 1 + lt_span[0] += 1 + initial_line += 1 + ct_span[0] = max(0, ct_span[0] - 1) + lt_span[0] = max(0, lt_span[0] - 1) + initial_line = max(cstart, initial_line - 1) + + lt = lt[lt_span[0]:lt_span[1]] + ct = ct[ct_span[0]:ct_span[1]] + + try: + rv, es = guess_edit(initial_line, lt, ct, self._vstate) + if not rv: + lt = '\n'.join(lt) + ct = '\n'.join(ct) + es = diff(lt, ct, initial_line) + self._csnippets[0].replay_user_edits(es) + except IndexError: + # Rather do nothing than throwing an error. It will be correct + # most of the time + pass + + self._check_if_still_inside_snippet() + if self._csnippets: + self._csnippets[0].update_textobjects() + self._vstate.remember_buffer(self._csnippets[0]) + + def _map_inner_keys(self): + """Map keys that should only be defined when a snippet is active.""" + if self.expand_trigger != self.forward_trigger: + _vim.command("inoremap " + self.forward_trigger + + " =UltiSnips#JumpForwards()") + _vim.command("snoremap " + self.forward_trigger + + " :call UltiSnips#JumpForwards()") + _vim.command("inoremap " + self.backward_trigger + + " =UltiSnips#JumpBackwards()") + _vim.command("snoremap " + self.backward_trigger + + " :call UltiSnips#JumpBackwards()") + self._inner_mappings_in_place = True + + def _unmap_inner_keys(self): + """Unmap keys that should not be active when no snippet is active.""" + if not self._inner_mappings_in_place: + return + try: + if self.expand_trigger != self.forward_trigger: + _vim.command("iunmap %s" % self.forward_trigger) + _vim.command("sunmap %s" % self.forward_trigger) + _vim.command("iunmap %s" % self.backward_trigger) + _vim.command("sunmap %s" % self.backward_trigger) + self._inner_mappings_in_place = False + except _vim.error: + # This happens when a preview window was opened. This issues + # CursorMoved, but not BufLeave. We have no way to unmap, until we + # are back in our buffer + pass + + @err_to_scratch_buffer + def _save_last_visual_selection(self): + """ + This is called when the expand trigger is pressed in visual mode. + Our job is to remember everything between '< and '> and pass it on to + ${VISUAL} in case it will be needed. + """ + self._visual_content.conserve() + + def _leaving_buffer(self): + """Called when the user switches tabs/windows/buffers. It basically + means that all snippets must be properly terminated.""" + while len(self._csnippets): + self._current_snippet_is_done() + self._reinit() + + def _reinit(self): + """Resets transient state.""" + self._ctab = None + self._ignore_movements = False + + def _check_if_still_inside_snippet(self): + """Checks if the cursor is outside of the current snippet.""" + if self._cs and ( + not self._cs.start <= _vim.buf.cursor <= self._cs.end + ): + self._current_snippet_is_done() + self._reinit() + self._check_if_still_inside_snippet() + + def _current_snippet_is_done(self): + """The current snippet should be terminated.""" + self._csnippets.pop() + if not self._csnippets: + self._unmap_inner_keys() + + def _jump(self, backwards=False): + """Helper method that does the actual jump.""" + jumped = False + # If next tab has length 1 and the distance between itself and + # self._ctab is 1 then there is 1 less CursorMove events. We + # cannot ignore next movement in such case. + ntab_short_and_near = False + if self._cs: + ntab = self._cs.select_next_tab(backwards) + if ntab: + if self._cs.snippet.has_option("s"): + lineno = _vim.buf.cursor.line + _vim.buf[lineno] = _vim.buf[lineno].rstrip() + _vim.select(ntab.start, ntab.end) + jumped = True + if (self._ctab is not None + and ntab.start - self._ctab.end == Position(0, 1) + and ntab.end - ntab.start == Position(0, 1)): + ntab_short_and_near = True + if ntab.number == 0: + self._current_snippet_is_done() + else: + # This really shouldn't happen, because a snippet should + # have been popped when its final tabstop was used. + # Cleanup by removing current snippet and recursing. + self._current_snippet_is_done() + jumped = self._jump(backwards) + self._ctab = ntab + if jumped: + self._vstate.remember_position() + self._vstate.remember_unnamed_register(self._ctab.current_text) + if not ntab_short_and_near: + self._ignore_movements = True + return jumped + + def _leaving_insert_mode(self): + """Called whenever we leave the insert mode.""" + self._vstate.restore_unnamed_register() + + def _handle_failure(self, trigger): + """Mainly make sure that we play well with SuperTab.""" + if trigger.lower() == "": + feedkey = "\\" + trigger + elif trigger.lower() == "": + feedkey = "\\" + trigger + else: + feedkey = None + mode = "n" + if not self._supertab_keys: + if _vim.eval("exists('g:SuperTabMappingForward')") != "0": + self._supertab_keys = ( + _vim.eval("g:SuperTabMappingForward"), + _vim.eval("g:SuperTabMappingBackward"), + ) + else: + self._supertab_keys = ['', ''] + + for idx, sttrig in enumerate(self._supertab_keys): + if trigger.lower() == sttrig.lower(): + if idx == 0: + feedkey = r"\SuperTabForward" + mode = "n" + elif idx == 1: + feedkey = r"\SuperTabBackward" + mode = "p" + # Use remap mode so SuperTab mappings will be invoked. + break + + if (feedkey == r"\SuperTabForward" or + feedkey == r"\SuperTabBackward"): + _vim.command("return SuperTab(%s)" % _vim.escape(mode)) + elif feedkey: + _vim.command("return %s" % _vim.escape(feedkey)) + + def _snips(self, before, partial): + """Returns all the snippets for the given text before the cursor. If + partial is True, then get also return partial matches. """ + filetypes = self._buffer_filetypes[_vim.buf.number][::-1] + matching_snippets = defaultdict(list) + clear_priority = None + cleared = {} + for _, source in self._snippet_sources: + source.ensure(filetypes) + + # Collect cleared information from sources. + for _, source in self._snippet_sources: + sclear_priority = source.get_clear_priority(filetypes) + if sclear_priority is not None and (clear_priority is None + or sclear_priority > clear_priority): + clear_priority = sclear_priority + for key, value in source.get_cleared(filetypes).items(): + if key not in cleared or value > cleared[key]: + cleared[key] = value + + for _, source in self._snippet_sources: + for snippet in source.get_snippets(filetypes, before, partial): + if ((clear_priority is None or snippet.priority > clear_priority) + and (snippet.trigger not in cleared or + snippet.priority > cleared[snippet.trigger])): + matching_snippets[snippet.trigger].append(snippet) + if not matching_snippets: + return [] + + # Now filter duplicates and only keep the one with the highest + # priority. + snippets = [] + for snippets_with_trigger in matching_snippets.values(): + highest_priority = max(s.priority for s in snippets_with_trigger) + snippets.extend(s for s in snippets_with_trigger + if s.priority == highest_priority) + + # For partial matches we are done, but if we want to expand a snippet, + # we have to go over them again and only keep those with the maximum + # priority. + if partial: + return snippets + + highest_priority = max(s.priority for s in snippets) + return [s for s in snippets if s.priority == highest_priority] + + def _do_snippet(self, snippet, before): + """Expands the given snippet, and handles everything + that needs to be done with it.""" + self._map_inner_keys() + + # Adjust before, maybe the trigger is not the complete word + text_before = before + if snippet.matched: + text_before = before[:-len(snippet.matched)] + + if self._cs: + start = Position(_vim.buf.cursor.line, len(text_before)) + end = Position(_vim.buf.cursor.line, len(before)) + + # It could be that our trigger contains the content of TextObjects + # in our containing snippet. If this is indeed the case, we have to + # make sure that those are properly killed. We do this by + # pretending that the user deleted and retyped the text that our + # trigger matched. + edit_actions = [ + ("D", start.line, start.col, snippet.matched), + ("I", start.line, start.col, snippet.matched), + ] + self._csnippets[0].replay_user_edits(edit_actions) + + si = snippet.launch(text_before, self._visual_content, + self._cs.find_parent_for_new_to(start), start, end) + else: + start = Position(_vim.buf.cursor.line, len(text_before)) + end = Position(_vim.buf.cursor.line, len(before)) + si = snippet.launch(text_before, self._visual_content, + None, start, end) + + self._visual_content.reset() + self._csnippets.append(si) + + si.update_textobjects() + + self._vstate.remember_buffer(self._csnippets[0]) + + self._jump() + + def _try_expand(self): + """Try to expand a snippet in the current place.""" + before = _vim.buf.line_till_cursor + if not before: + return False + snippets = self._snips(before, False) + if not snippets: + # No snippet found + return False + elif len(snippets) == 1: + snippet = snippets[0] + else: + snippet = _ask_snippets(snippets) + if not snippet: + return True + self._do_snippet(snippet, before) + return True + + @property + def _cs(self): + """The current snippet or None.""" + if not len(self._csnippets): + return None + return self._csnippets[-1] + + def _file_to_edit(self, requested_ft, bang): # pylint: disable=no-self-use + """Returns a file to be edited for the given requested_ft. If 'bang' is + empty only private files in g:UltiSnipsSnippetsDir are considered, + otherwise all files are considered and the user gets to choose. + """ + # This method is not using self, but is called by UltiSnips.vim and is + # therefore in this class because it is the facade to Vim. + potentials = set() + + if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == "1": + snippet_dir = _vim.eval("g:UltiSnipsSnippetsDir") + else: + if platform.system() == "Windows": + snippet_dir = os.path.join(_vim.eval("$HOME"), + "vimfiles", "UltiSnips") + else: + snippet_dir = os.path.join(_vim.eval("$HOME"), + ".vim", "UltiSnips") + + filetypes = [] + if requested_ft: + filetypes.append(requested_ft) + else: + if bang: + filetypes.extend(self._buffer_filetypes[_vim.buf.number]) + else: + filetypes.append(self._buffer_filetypes[_vim.buf.number][0]) + + for ft in filetypes: + potentials.update(find_snippet_files(ft, snippet_dir)) + potentials.add(os.path.join(snippet_dir, + ft + '.snippets')) + if bang: + potentials.update(find_all_snippet_files(ft)) + + potentials = set(os.path.realpath(os.path.expanduser(p)) + for p in potentials) + + if len(potentials) > 1: + files = sorted(potentials) + formatted = [as_unicode('%i: %s') % (i, escape(fn, '\\')) for + i, fn in enumerate(files, 1)] + file_to_edit = _ask_user(files, formatted) + if file_to_edit is None: + return "" + else: + file_to_edit = potentials.pop() + + dirname = os.path.dirname(file_to_edit) + if not os.path.exists(dirname): + os.makedirs(dirname) + return file_to_edit diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/test_diff.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/test_diff.py new file mode 100644 index 0000000..6e13e73 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/test_diff.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# pylint: skip-file + +import unittest + +from _diff import diff, guess_edit +from position import Position + + +def transform(a, cmds): + buf = a.split("\n") + + for cmd in cmds: + ctype, line, col, char = cmd + if ctype == "D": + if char != '\n': + buf[line] = buf[line][:col] + buf[line][col+len(char):] + else: + buf[line] = buf[line] + buf[line+1] + del buf[line+1] + elif ctype == "I": + buf[line] = buf[line][:col] + char + buf[line][col:] + buf = '\n'.join(buf).split('\n') + return '\n'.join(buf) + + +import unittest + +# Test Guessing {{{ +class _BaseGuessing(object): + def runTest(self): + rv, es = guess_edit(self.initial_line, self.a, self.b, Position(*self.ppos), Position(*self.pos)) + self.assertEqual(rv, True) + self.assertEqual(self.wanted, es) + +class TestGuessing_Noop0(_BaseGuessing, unittest.TestCase): + a, b = [], [] + initial_line = 0 + ppos, pos = (0, 6), (0, 7) + wanted = () + +class TestGuessing_InsertOneChar(_BaseGuessing, unittest.TestCase): + a, b = ["Hello World"], ["Hello World"] + initial_line = 0 + ppos, pos = (0, 6), (0, 7) + wanted = ( + ("I", 0, 6, " "), + ) +class TestGuessing_InsertOneChar1(_BaseGuessing, unittest.TestCase): + a, b = ["Hello World"], ["Hello World"] + initial_line = 0 + ppos, pos = (0, 7), (0, 8) + wanted = ( + ("I", 0, 7, " "), + ) +class TestGuessing_BackspaceOneChar(_BaseGuessing, unittest.TestCase): + a, b = ["Hello World"], ["Hello World"] + initial_line = 0 + ppos, pos = (0, 7), (0, 6) + wanted = ( + ("D", 0, 6, " "), + ) +class TestGuessing_DeleteOneChar(_BaseGuessing, unittest.TestCase): + a, b = ["Hello World"], ["Hello World"] + initial_line = 0 + ppos, pos = (0, 5), (0, 5) + wanted = ( + ("D", 0, 5, " "), + ) + +# End: Test Guessing }}} + +class _Base(object): + def runTest(self): + es = diff(self.a, self.b) + tr = transform(self.a, es) + self.assertEqual(self.b, tr) + self.assertEqual(self.wanted, es) + +class TestEmptyString(_Base, unittest.TestCase): + a, b = "", "" + wanted = () + +class TestAllMatch(_Base, unittest.TestCase): + a, b = "abcdef", "abcdef" + wanted = () + +class TestLotsaNewlines(_Base, unittest.TestCase): + a, b = "Hello", "Hello\nWorld\nWorld\nWorld" + wanted = ( + ("I", 0, 5, "\n"), + ("I", 1, 0, "World"), + ("I", 1, 5, "\n"), + ("I", 2, 0, "World"), + ("I", 2, 5, "\n"), + ("I", 3, 0, "World"), + ) + +class TestCrash(_Base, unittest.TestCase): + a = 'hallo Blah mitte=sdfdsfsd\nhallo kjsdhfjksdhfkjhsdfkh mittekjshdkfhkhsdfdsf' + b = 'hallo Blah mitte=sdfdsfsd\nhallo b mittekjshdkfhkhsdfdsf' + wanted = ( + ("D", 1, 6, "kjsdhfjksdhfkjhsdfkh"), + ("I", 1, 6, "b"), + ) + +class TestRealLife(_Base, unittest.TestCase): + a = 'hallo End Beginning' + b = 'hallo End t' + wanted = ( + ("D", 0, 10, "Beginning"), + ("I", 0, 10, "t"), + ) + +class TestRealLife1(_Base, unittest.TestCase): + a = 'Vorne hallo Hinten' + b = 'Vorne hallo Hinten' + wanted = ( + ("I", 0, 11, " "), + ) + +class TestWithNewline(_Base, unittest.TestCase): + a = 'First Line\nSecond Line' + b = 'n' + wanted = ( + ("D", 0, 0, "First Line"), + ("D", 0, 0, "\n"), + ("D", 0, 0, "Second Line"), + ("I", 0, 0, "n"), + ) + + +class TestCheapDelete(_Base, unittest.TestCase): + a = 'Vorne hallo Hinten' + b = 'Vorne Hinten' + wanted = ( + ("D", 0, 5, " hallo"), + ) + +class TestNoSubstring(_Base, unittest.TestCase): + a,b = "abc", "def" + wanted = ( + ("D", 0, 0, "abc"), + ("I", 0, 0, "def"), + ) + +class TestCommonCharacters(_Base, unittest.TestCase): + a,b = "hasomelongertextbl", "hol" + wanted = ( + ("D", 0, 1, "asomelongertextb"), + ("I", 0, 1, "o"), + ) + +class TestUltiSnipsProblem(_Base, unittest.TestCase): + a = "this is it this is it this is it" + b = "this is it a this is it" + wanted = ( + ("D", 0, 11, "this is it"), + ("I", 0, 11, "a"), + ) + +class MatchIsTooCheap(_Base, unittest.TestCase): + a = "stdin.h" + b = "s" + wanted = ( + ("D", 0, 1, "tdin.h"), + ) + +class MultiLine(_Base, unittest.TestCase): + a = "hi first line\nsecond line first line\nsecond line world" + b = "hi first line\nsecond line k world" + + wanted = ( + ("D", 1, 12, "first line"), + ("D", 1, 12, "\n"), + ("D", 1, 12, "second line"), + ("I", 1, 12, "k"), + ) + + +if __name__ == '__main__': + unittest.main() + # k = TestEditScript() + # unittest.TextTestRunner().run(k) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/test_position.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/test_position.py new file mode 100644 index 0000000..7c209a3 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/test_position.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# pylint: skip-file + +import unittest + +from position import Position + +class _MPBase(object): + def runTest(self): + obj = Position(*self.obj) + for pivot, delta, wanted in self.steps: + obj.move(Position(*pivot), Position(*delta)) + self.assertEqual(Position(*wanted), obj) + +class MovePosition_DelSameLine(_MPBase, unittest.TestCase): + # hello wor*ld -> h*ld -> hl*ld + obj = (0, 9) + steps = ( + ((0, 1), (0, -8), (0, 1)), + ((0, 1), (0, 1), (0, 2)), + ) +class MovePosition_DelSameLine1(_MPBase, unittest.TestCase): + # hel*lo world -> hel*world -> hel*worl + obj = (0,3) + steps = ( + ((0, 4), (0, -3), (0,3)), + ((0, 8), (0, -1), (0,3)), + ) +class MovePosition_InsSameLine1(_MPBase, unittest.TestCase): + # hel*lo world -> hel*woresld + obj = (0, 3) + steps = ( + ((0, 4), (0, -3), (0, 3)), + ((0, 6), (0, 2), (0, 3)), + ((0, 8), (0, -1), (0, 3)) + ) +class MovePosition_InsSameLine2(_MPBase, unittest.TestCase): + # hello wor*ld -> helesdlo wor*ld + obj = (0, 9) + steps = ( + ((0, 3), (0, 3), (0, 12)), + ) + +class MovePosition_DelSecondLine(_MPBase, unittest.TestCase): + # hello world. sup hello world.*a, was + # *a, was ach nix + # ach nix + obj = (1, 0) + steps = ( + ((0, 12), (0, -4), (1, 0)), + ((0, 12), (-1, 0), (0, 12)), + ) +class MovePosition_DelSecondLine1(_MPBase, unittest.TestCase): + # hello world. sup + # a, *was + # ach nix + # hello world.a*was + # ach nix + obj = (1, 3) + steps = ( + ((0, 12), (0, -4), (1, 3)), + ((0, 12), (-1, 0), (0, 15)), + ((0, 12), (0, -3), (0, 12)), + ((0, 12), (0, 1), (0, 13)), + ) + +if __name__ == '__main__': + unittest.main() diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text.py new file mode 100644 index 0000000..a47a928 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Utilities to deal with text.""" + +def unescape(text): + """Removes '\\' escaping from 'text'.""" + rv = "" + i = 0 + while i < len(text): + if i+1 < len(text) and text[i] == '\\': + rv += text[i+1] + i += 1 + else: + rv += text[i] + i += 1 + return rv + +def escape(text, chars): + """Escapes all characters in 'chars' in text using backspaces.""" + rv = "" + for char in text: + if char in chars: + rv += '\\' + rv += char + return rv + + +def fill_in_whitespace(text): + """Returns 'text' with escaped whitespace replaced through whitespaces.""" + text = text.replace(r"\n", "\n") + text = text.replace(r"\t", "\t") + text = text.replace(r"\r", "\r") + text = text.replace(r"\a", "\a") + text = text.replace(r"\b", "\b") + return text + +def head_tail(line): + """Returns the first word in 'line' and the rest of 'line' or None if the + line is too short.""" + generator = (t.strip() for t in line.split(None, 1)) + head = next(generator).strip() + tail = '' + try: + tail = next(generator).strip() + except StopIteration: + pass + return head, tail + +class LineIterator(object): + """Convenience class that keeps track of line numbers in files.""" + + def __init__(self, text): + self._line_index = -1 + self._lines = list(text.splitlines(True)) + + def __iter__(self): + return self + + def __next__(self): + """Returns the next line.""" + if self._line_index + 1 < len(self._lines): + self._line_index += 1 + return self._lines[self._line_index] + raise StopIteration() + next = __next__ # for python2 + + @property + def line_index(self): + """The 1 based line index in the current file.""" + return self._line_index + 1 + + def peek(self): + """Returns the next line (if there is any, otherwise None) without + advancing the iterator.""" + try: + return self._lines[self._line_index + 1] + except IndexError: + return None diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/__init__.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/__init__.py new file mode 100644 index 0000000..97e2252 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/__init__.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Public facing classes for TextObjects.""" + +from UltiSnips.text_objects._escaped_char import EscapedChar +from UltiSnips.text_objects._mirror import Mirror +from UltiSnips.text_objects._python_code import PythonCode +from UltiSnips.text_objects._shell_code import ShellCode +from UltiSnips.text_objects._snippet_instance import SnippetInstance +from UltiSnips.text_objects._tabstop import TabStop +from UltiSnips.text_objects._transformation import Transformation +from UltiSnips.text_objects._viml_code import VimLCode +from UltiSnips.text_objects._visual import Visual diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_base.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_base.py new file mode 100644 index 0000000..0809bb9 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_base.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Base classes for all text objects.""" + +from UltiSnips import _vim +from UltiSnips.position import Position + +def _calc_end(text, start): + """Calculate the end position of the 'text' starting at 'start.""" + if len(text) == 1: + new_end = start + Position(0, len(text[0])) + else: + new_end = Position(start.line + len(text)-1, len(text[-1])) + return new_end + +def _text_to_vim(start, end, text): + """Copy the given text to the current buffer, overwriting the span 'start' + to 'end'.""" + lines = text.split('\n') + + new_end = _calc_end(lines, start) + + before = _vim.buf[start.line][:start.col] + after = _vim.buf[end.line][end.col:] + + new_lines = [] + if len(lines): + new_lines.append(before + lines[0]) + new_lines.extend(lines[1:]) + new_lines[-1] += after + _vim.buf[start.line:end.line + 1] = new_lines + + # Open any folds this might have created + _vim.buf.cursor = start + _vim.command("normal! zv") + + return new_end + +# These classes use their subclasses a lot and we really do not want to expose +# their functions more globally. +# pylint: disable=protected-access +class TextObject(object): + """Represents any object in the text that has a span in any ways.""" + + def __init__(self, parent, token, end=None, + initial_text="", tiebreaker=None): + self._parent = parent + + if end is not None: # Took 4 arguments + self._start = token + self._end = end + self._initial_text = initial_text + else: # Initialize from token + self._start = token.start + self._end = token.end + self._initial_text = token.initial_text + self._tiebreaker = tiebreaker or Position( + self._start.line, self._end.line) + if parent is not None: + parent._add_child(self) + + def _move(self, pivot, diff): + """Move this object by 'diff' while 'pivot' is the point of change.""" + self._start.move(pivot, diff) + self._end.move(pivot, diff) + + def __lt__(self, other): + me_tuple = (self.start.line, self.start.col, + self._tiebreaker.line, self._tiebreaker.col) + other_tuple = (other._start.line, other._start.col, + other._tiebreaker.line, other._tiebreaker.col) + return me_tuple < other_tuple + + def __le__(self, other): + me_tuple = (self._start.line, self._start.col, + self._tiebreaker.line, self._tiebreaker.col) + other_tuple = (other._start.line, other._start.col, + other._tiebreaker.line, other._tiebreaker.col) + return me_tuple <= other_tuple + + def __repr__(self): + ct = "" + try: + ct = self.current_text + except IndexError: + ct = "" + + return "%s(%r->%r,%r)" % (self.__class__.__name__, + self._start, self._end, ct) + + @property + def current_text(self): + """The current text of this object.""" + if self._start.line == self._end.line: + return _vim.buf[self._start.line][self._start.col:self._end.col] + else: + lines = [_vim.buf[self._start.line][self._start.col:]] + lines.extend(_vim.buf[self._start.line+1:self._end.line]) + lines.append(_vim.buf[self._end.line][:self._end.col]) + return '\n'.join(lines) + + @property + def start(self): + """The start position.""" + return self._start + + @property + def end(self): + """The end position.""" + return self._end + + def overwrite(self, gtext=None): + """Overwrite the text of this object in the Vim Buffer and update its + length information. If 'gtext' is None use the initial text of this + object. + """ + # We explicitly do not want to move our children around here as we + # either have non or we are replacing text initially which means we do + # not want to mess with their positions + if self.current_text == gtext: + return + old_end = self._end + self._end = _text_to_vim( + self._start, self._end, gtext or self._initial_text) + if self._parent: + self._parent._child_has_moved( + self._parent._children.index(self), min(old_end, self._end), + self._end.delta(old_end) + ) + + def _update(self, done): + """Update this object inside the Vim Buffer. + + Return False if you need to be called again for this edit cycle. + Otherwise return True. + """ + raise NotImplementedError("Must be implemented by subclasses.") + +class EditableTextObject(TextObject): + """ + This base class represents any object in the text + that can be changed by the user + """ + def __init__(self, *args, **kwargs): + TextObject.__init__(self, *args, **kwargs) + self._children = [] + self._tabstops = {} + + ############## + # Properties # + ############## + @property + def children(self): + """List of all children.""" + return self._children + + @property + def _editable_children(self): + """List of all children that are EditableTextObjects""" + return [child for child in self._children if + isinstance(child, EditableTextObject)] + + #################### + # Public Functions # + #################### + def find_parent_for_new_to(self, pos): + """Figure out the parent object for something at 'pos'.""" + for children in self._editable_children: + if children._start <= pos < children._end: + return children.find_parent_for_new_to(pos) + return self + + ############################### + # Private/Protected functions # + ############################### + def _do_edit(self, cmd): + """Apply the edit 'cmd' to this object.""" + ctype, line, col, text = cmd + assert ('\n' not in text) or (text == "\n") + pos = Position(line, col) + + to_kill = set() + new_cmds = [] + for child in self._children: + if ctype == "I": # Insertion + if (child._start < pos < + Position(child._end.line, child._end.col) and + isinstance(child, NoneditableTextObject)): + to_kill.add(child) + new_cmds.append(cmd) + break + elif ((child._start <= pos <= child._end) and + isinstance(child, EditableTextObject)): + child._do_edit(cmd) + return + else: # Deletion + delend = pos + Position(0, len(text)) if text != "\n" \ + else Position(line + 1, 0) + if ((child._start <= pos < child._end) and + (child._start < delend <= child._end)): + # this edit command is completely for the child + if isinstance(child, NoneditableTextObject): + to_kill.add(child) + new_cmds.append(cmd) + break + else: + child._do_edit(cmd) + return + elif ((pos < child._start and child._end <= delend) or + (pos <= child._start and child._end < delend)): + # Case: this deletion removes the child + to_kill.add(child) + new_cmds.append(cmd) + break + elif (pos < child._start and + (child._start < delend <= child._end)): + # Case: partially for us, partially for the child + my_text = text[:(child._start-pos).col] + c_text = text[(child._start-pos).col:] + new_cmds.append((ctype, line, col, my_text)) + new_cmds.append((ctype, line, col, c_text)) + break + elif (delend >= child._end and ( + child._start <= pos < child._end)): + # Case: partially for us, partially for the child + c_text = text[(child._end-pos).col:] + my_text = text[:(child._end-pos).col] + new_cmds.append((ctype, line, col, c_text)) + new_cmds.append((ctype, line, col, my_text)) + break + + for child in to_kill: + self._del_child(child) + if len(new_cmds): + for child in new_cmds: + self._do_edit(child) + return + + # We have to handle this ourselves + delta = Position(1, 0) if text == "\n" else Position(0, len(text)) + if ctype == "D": + # Makes no sense to delete in empty textobject + if self._start == self._end: + return + delta.line *= -1 + delta.col *= -1 + pivot = Position(line, col) + idx = -1 + for cidx, child in enumerate(self._children): + if child._start < pivot <= child._end: + idx = cidx + self._child_has_moved(idx, pivot, delta) + + def _move(self, pivot, diff): + TextObject._move(self, pivot, diff) + + for child in self._children: + child._move(pivot, diff) + + def _child_has_moved(self, idx, pivot, diff): + """Called when a the child with 'idx' has moved behind 'pivot' by + 'diff'.""" + self._end.move(pivot, diff) + + for child in self._children[idx+1:]: + child._move(pivot, diff) + + if self._parent: + self._parent._child_has_moved( + self._parent._children.index(self), pivot, diff + ) + + def _get_next_tab(self, number): + """Returns the next tabstop after 'number'.""" + if not len(self._tabstops.keys()): + return + tno_max = max(self._tabstops.keys()) + + possible_sol = [] + i = number + 1 + while i <= tno_max: + if i in self._tabstops: + possible_sol.append((i, self._tabstops[i])) + break + i += 1 + + child = [c._get_next_tab(number) for c in self._editable_children] + child = [c for c in child if c] + + possible_sol += child + + if not len(possible_sol): + return None + + return min(possible_sol) + + + def _get_prev_tab(self, number): + """Returns the previous tabstop before 'number'.""" + if not len(self._tabstops.keys()): + return + tno_min = min(self._tabstops.keys()) + + possible_sol = [] + i = number - 1 + while i >= tno_min and i > 0: + if i in self._tabstops: + possible_sol.append((i, self._tabstops[i])) + break + i -= 1 + + child = [c._get_prev_tab(number) for c in self._editable_children] + child = [c for c in child if c] + + possible_sol += child + + if not len(possible_sol): + return None + + return max(possible_sol) + + def _get_tabstop(self, requester, number): + """Returns the tabstop 'number'. 'requester' is the class that is + interested in this.""" + if number in self._tabstops: + return self._tabstops[number] + for child in self._editable_children: + if child is requester: + continue + rv = child._get_tabstop(self, number) + if rv is not None: + return rv + if self._parent and requester is not self._parent: + return self._parent._get_tabstop(self, number) + + def _update(self, done): + if all((child in done) for child in self._children): + assert self not in done + done.add(self) + return True + + def _add_child(self, child): + """Add 'child' as a new child of this text object.""" + self._children.append(child) + self._children.sort() + + def _del_child(self, child): + """Delete this 'child'.""" + child._parent = None + self._children.remove(child) + + # If this is a tabstop, delete it. Might have been deleted already if + # it was nested. + try: + del self._tabstops[child.number] + except (AttributeError, KeyError): + pass + +class NoneditableTextObject(TextObject): + """All passive text objects that the user can't edit by hand.""" + def _update(self, done): + return True diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_escaped_char.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_escaped_char.py new file mode 100644 index 0000000..c197abd --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_escaped_char.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""See module comment.""" + +from UltiSnips.text_objects._base import NoneditableTextObject + +class EscapedChar(NoneditableTextObject): + r""" + This class is a escape char like \$. It is handled in a text object to make + sure that siblings are correctly moved after replacing the text. + + This is a base class without functionality just to mark it in the code. + """ + pass diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_mirror.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_mirror.py new file mode 100644 index 0000000..b4e512c --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_mirror.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""A Mirror object contains the same text as its related tabstop.""" + +from UltiSnips.text_objects._base import NoneditableTextObject + +class Mirror(NoneditableTextObject): + """See module docstring.""" + + def __init__(self, parent, tabstop, token): + NoneditableTextObject.__init__(self, parent, token) + + self._ts = tabstop + + def _update(self, done): + if self._ts.is_killed: + self.overwrite("") + self._parent._del_child(self) # pylint:disable=protected-access + return True + + if self._ts not in done: + return False + + self.overwrite(self._get_text()) + return True + + def _get_text(self): + """Returns the text used for mirroring. Overwritten by base classes.""" + return self._ts.current_text diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_python_code.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_python_code.py new file mode 100644 index 0000000..e4473f1 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_python_code.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Implements `!p ` interpolation.""" + +import os +from collections import namedtuple + +from UltiSnips import _vim +from UltiSnips.compatibility import as_unicode +from UltiSnips.indent_util import IndentUtil +from UltiSnips.text_objects._base import NoneditableTextObject + + +class _Tabs(object): + """Allows access to tabstop content via t[] inside of python code.""" + def __init__(self, to): + self._to = to + + def __getitem__(self, no): + ts = self._to._get_tabstop(self._to, int(no)) # pylint:disable=protected-access + if ts is None: + return "" + return ts.current_text + +_VisualContent = namedtuple('_VisualContent', ['mode', 'text']) + +class SnippetUtil(object): + """Provides easy access to indentation, etc. This is the 'snip' object in + python code.""" + + def __init__(self, initial_indent, vmode, vtext): + self._ind = IndentUtil() + self._visual = _VisualContent(vmode, vtext) + self._initial_indent = self._ind.indent_to_spaces(initial_indent) + self._reset("") + + def _reset(self, cur): + """Gets the snippet ready for another update. + :cur: the new value for c. + """ + self._ind.reset() + self._cur = cur + self._rv = "" + self._changed = False + self.reset_indent() + + def shift(self, amount=1): + """Shifts the indentation level. + Note that this uses the shiftwidth because thats what code + formatters use. + + :amount: the amount by which to shift. + """ + self.indent += " " * self._ind.shiftwidth * amount + + def unshift(self, amount=1): + """Unshift the indentation level. + Note that this uses the shiftwidth because thats what code + formatters use. + + :amount: the amount by which to unshift. + """ + by = -self._ind.shiftwidth * amount + try: + self.indent = self.indent[:by] + except IndexError: + self.indent = "" + + def mkline(self, line="", indent=None): + """Creates a properly set up line. + + :line: the text to add + :indent: the indentation to have at the beginning + if None, it uses the default amount + """ + if indent is None: + indent = self.indent + # this deals with the fact that the first line is + # already properly indented + if '\n' not in self._rv: + try: + indent = indent[len(self._initial_indent):] + except IndexError: + indent = "" + indent = self._ind.spaces_to_indent(indent) + + return indent + line + + def reset_indent(self): + """Clears the indentation.""" + self.indent = self._initial_indent + + # Utility methods + @property + def fn(self): # pylint:disable=no-self-use,invalid-name + """The filename.""" + return _vim.eval('expand("%:t")') or "" + + @property + def basename(self): # pylint:disable=no-self-use + """The filename without extension.""" + return _vim.eval('expand("%:t:r")') or "" + + @property + def ft(self): # pylint:disable=invalid-name + """The filetype.""" + return self.opt("&filetype", "") + + @property + def rv(self): # pylint:disable=invalid-name + """The return value. The text to insert at the location of the + placeholder.""" + return self._rv + + @rv.setter + def rv(self, value): # pylint:disable=invalid-name + """See getter.""" + self._changed = True + self._rv = value + + @property + def _rv_changed(self): + """True if rv has changed.""" + return self._changed + + @property + def c(self): # pylint:disable=invalid-name + """The current text of the placeholder.""" + return self._cur + + @property + def v(self): # pylint:disable=invalid-name + """Content of visual expansions""" + return self._visual + + def opt(self, option, default=None): # pylint:disable=no-self-use + """Gets a Vim variable.""" + if _vim.eval("exists('%s')" % option) == "1": + try: + return _vim.eval(option) + except _vim.error: + pass + return default + + def __add__(self, value): + """Appends the given line to rv using mkline.""" + self.rv += '\n' # pylint:disable=invalid-name + self.rv += self.mkline(value) + return self + + def __lshift__(self, other): + """Same as unshift.""" + self.unshift(other) + + def __rshift__(self, other): + """Same as shift.""" + self.shift(other) + + +class PythonCode(NoneditableTextObject): + """See module docstring.""" + + def __init__(self, parent, token): + + # Find our containing snippet for snippet local data + snippet = parent + while snippet: + try: + self._locals = snippet.locals + text = snippet.visual_content.text + mode = snippet.visual_content.mode + break + except AttributeError: + snippet = snippet._parent # pylint:disable=protected-access + self._snip = SnippetUtil(token.indent, mode, text) + + self._codes = (( + "import re, os, vim, string, random", + "\n".join(snippet.globals.get("!p", [])).replace("\r\n", "\n"), + token.code.replace("\\`", "`") + )) + NoneditableTextObject.__init__(self, parent, token) + + def _update(self, done): + path = _vim.eval('expand("%")') or "" + ct = self.current_text + self._locals.update({ + 't': _Tabs(self._parent), + 'fn': os.path.basename(path), + 'path': path, + 'cur': ct, + 'res': ct, + 'snip': self._snip, + }) + self._snip._reset(ct) # pylint:disable=protected-access + + for code in self._codes: + exec(code, self._locals) # pylint:disable=exec-used + + rv = as_unicode( + self._snip.rv if self._snip._rv_changed # pylint:disable=protected-access + else as_unicode(self._locals['res']) + ) + + if ct != rv: + self.overwrite(rv) + return False + return True diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_shell_code.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_shell_code.py new file mode 100644 index 0000000..3e9099a --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_shell_code.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Implements `echo hi` shell code interpolation.""" + +import os +import platform +from subprocess import Popen, PIPE +import stat +import tempfile + +from UltiSnips.compatibility import as_unicode +from UltiSnips.text_objects._base import NoneditableTextObject + +def _chomp(string): + """Rather than rstrip(), remove only the last newline and preserve + purposeful whitespace.""" + if len(string) and string[-1] == '\n': + string = string[:-1] + if len(string) and string[-1] == '\r': + string = string[:-1] + return string + +def _run_shell_command(cmd, tmpdir): + """Write the code to a temporary file""" + cmdsuf = '' + if platform.system() == 'Windows': + # suffix required to run command on windows + cmdsuf = '.bat' + # turn echo off + cmd = '@echo off\r\n' + cmd + handle, path = tempfile.mkstemp(text=True, dir=tmpdir, suffix=cmdsuf) + os.write(handle, cmd.encode("utf-8")) + os.close(handle) + os.chmod(path, stat.S_IRWXU) + + # Execute the file and read stdout + proc = Popen(path, shell=True, stdout=PIPE, stderr=PIPE) + proc.wait() + stdout, _ = proc.communicate() + os.unlink(path) + return _chomp(as_unicode(stdout)) + +def _get_tmp(): + """Find an executable tmp directory.""" + userdir = os.path.expanduser("~") + for testdir in [tempfile.gettempdir(), os.path.join(userdir, '.cache'), + os.path.join(userdir, '.tmp'), userdir]: + if (not os.path.exists(testdir) or + not _run_shell_command('echo success', testdir) == 'success'): + continue + return testdir + return '' + +class ShellCode(NoneditableTextObject): + """See module docstring.""" + + def __init__(self, parent, token): + NoneditableTextObject.__init__(self, parent, token) + self._code = token.code.replace("\\`", "`") + self._tmpdir = _get_tmp() + + def _update(self, done): + if not self._tmpdir: + output = \ + "Unable to find executable tmp directory, check noexec on /tmp" + else: + output = _run_shell_command(self._code, self._tmpdir) + self.overwrite(output) + self._parent._del_child(self) # pylint:disable=protected-access + return True diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_snippet_instance.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_snippet_instance.py new file mode 100644 index 0000000..71beb00 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_snippet_instance.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""A Snippet instance is an instance of a Snippet Definition. That is, when the +user expands a snippet, a SnippetInstance is created to keep track of the +corresponding TextObjects. The Snippet itself is also a TextObject. """ + +from UltiSnips import _vim +from UltiSnips.position import Position +from UltiSnips.text_objects._base import EditableTextObject, \ + NoneditableTextObject + +class SnippetInstance(EditableTextObject): + """See module docstring.""" + # pylint:disable=protected-access + + def __init__(self, snippet, parent, initial_text, + start, end, visual_content, last_re, globals): + if start is None: + start = Position(0, 0) + if end is None: + end = Position(0, 0) + self.snippet = snippet + self._cts = 0 + + self.locals = {"match" : last_re} + self.globals = globals + self.visual_content = visual_content + + EditableTextObject.__init__(self, parent, start, end, initial_text) + + def replace_initial_text(self): + """Puts the initial text of all text elements into Vim.""" + def _place_initial_text(obj): + """recurses on the children to do the work.""" + obj.overwrite() + if isinstance(obj, EditableTextObject): + for child in obj._children: + _place_initial_text(child) + _place_initial_text(self) + + def replay_user_edits(self, cmds): + """Replay the edits the user has done to keep endings of our + Text objects in sync with reality""" + for cmd in cmds: + self._do_edit(cmd) + + def update_textobjects(self): + """Update the text objects that should change automagically after + the users edits have been replayed. This might also move the Cursor + """ + vc = _VimCursor(self) + done = set() + not_done = set() + def _find_recursive(obj): + """Finds all text objects and puts them into 'not_done'.""" + if isinstance(obj, EditableTextObject): + for child in obj._children: + _find_recursive(child) + not_done.add(obj) + _find_recursive(self) + + counter = 10 + while (done != not_done) and counter: + # Order matters for python locals! + for obj in sorted(not_done - done): + if obj._update(done): + done.add(obj) + counter -= 1 + if not counter: + raise RuntimeError( + "The snippets content did not converge: Check for Cyclic " + "dependencies or random strings in your snippet. You can use " + "'if not snip.c' to make sure to only expand random output " + "once.") + vc.to_vim() + self._del_child(vc) + + def select_next_tab(self, backwards=False): + """Selects the next tabstop or the previous if 'backwards' is True.""" + if self._cts is None: + return + + if backwards: + cts_bf = self._cts + + res = self._get_prev_tab(self._cts) + if res is None: + self._cts = cts_bf + return self._tabstops.get(self._cts, None) + self._cts, ts = res + return ts + else: + res = self._get_next_tab(self._cts) + if res is None: + self._cts = None + return self._tabstops.get(0, None) + else: + self._cts, ts = res + return ts + + return self._tabstops[self._cts] + + def _get_tabstop(self, requester, no): + # SnippetInstances are completely self contained, therefore, we do not + # need to ask our parent for Tabstops + cached_parent = self._parent + self._parent = None + rv = EditableTextObject._get_tabstop(self, requester, no) + self._parent = cached_parent + return rv + + +class _VimCursor(NoneditableTextObject): + """Helper class to keep track of the Vim Cursor when text objects expand + and move.""" + + def __init__(self, parent): + NoneditableTextObject.__init__( + self, parent, _vim.buf.cursor, _vim.buf.cursor, + tiebreaker=Position(-1, -1)) + + def to_vim(self): + """Moves the cursor in the Vim to our position.""" + assert self._start == self._end + _vim.buf.cursor = self._start diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_tabstop.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_tabstop.py new file mode 100644 index 0000000..ef0cb87 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_tabstop.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""This is the most important TextObject. A TabStop is were the cursor +comes to rest when the user taps through the Snippet.""" + +from UltiSnips.text_objects._base import EditableTextObject + +class TabStop(EditableTextObject): + """See module docstring.""" + + def __init__(self, parent, token, start=None, end=None): + if start is not None: + self._number = token + EditableTextObject.__init__(self, parent, start, end) + else: + self._number = token.number + EditableTextObject.__init__(self, parent, token) + parent._tabstops[self._number] = self # pylint:disable=protected-access + + @property + def number(self): + """The tabstop number.""" + return self._number + + @property + def is_killed(self): + """True if this tabstop has been typed over and the user therefore can + no longer jump to it.""" + return self._parent is None + + def __repr__(self): + return "TabStop(%s,%r->%r,%r)" % (self.number, self._start, + self._end, self.current_text) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_transformation.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_transformation.py new file mode 100644 index 0000000..6674a33 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_transformation.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Implements TabStop transformations.""" + +import re +import sys + +from UltiSnips.text import unescape, fill_in_whitespace +from UltiSnips.text_objects._mirror import Mirror + +def _find_closing_brace(string, start_pos): + """Finds the corresponding closing brace after start_pos.""" + bracks_open = 1 + for idx, char in enumerate(string[start_pos:]): + if char == '(': + if string[idx+start_pos-1] != '\\': + bracks_open += 1 + elif char == ')': + if string[idx+start_pos-1] != '\\': + bracks_open -= 1 + if not bracks_open: + return start_pos+idx+1 + +def _split_conditional(string): + """Split the given conditional 'string' into its arguments.""" + bracks_open = 0 + args = [] + carg = "" + for idx, char in enumerate(string): + if char == '(': + if string[idx-1] != '\\': + bracks_open += 1 + elif char == ')': + if string[idx-1] != '\\': + bracks_open -= 1 + elif char == ':' and not bracks_open and not string[idx-1] == '\\': + args.append(carg) + carg = "" + continue + carg += char + args.append(carg) + return args + +def _replace_conditional(match, string): + """Replaces a conditional match in a transformation.""" + conditional_match = _CONDITIONAL.search(string) + while conditional_match: + start = conditional_match.start() + end = _find_closing_brace(string, start+4) + args = _split_conditional(string[start+4:end-1]) + rv = "" + if match.group(int(conditional_match.group(1))): + rv = unescape(_replace_conditional(match, args[0])) + elif len(args) > 1: + rv = unescape(_replace_conditional(match, args[1])) + string = string[:start] + rv + string[end:] + conditional_match = _CONDITIONAL.search(string) + return string + +_ONE_CHAR_CASE_SWITCH = re.compile(r"\\([ul].)", re.DOTALL) +_LONG_CASEFOLDINGS = re.compile(r"\\([UL].*?)\\E", re.DOTALL) +_DOLLAR = re.compile(r"\$(\d+)", re.DOTALL) +_CONDITIONAL = re.compile(r"\(\?(\d+):", re.DOTALL) +class _CleverReplace(object): + """Mimics TextMates replace syntax.""" + + def __init__(self, expression): + self._expression = expression + + def replace(self, match): + """Replaces 'match' through the correct replacement string.""" + transformed = self._expression + # Replace all $? with capture groups + transformed = _DOLLAR.subn( + lambda m: match.group(int(m.group(1))), transformed)[0] + + # Replace Case switches + def _one_char_case_change(match): + """Replaces one character case changes.""" + if match.group(1)[0] == 'u': + return match.group(1)[-1].upper() + else: + return match.group(1)[-1].lower() + transformed = _ONE_CHAR_CASE_SWITCH.subn( + _one_char_case_change, transformed)[0] + + def _multi_char_case_change(match): + """Replaces multi character case changes.""" + if match.group(1)[0] == 'U': + return match.group(1)[1:].upper() + else: + return match.group(1)[1:].lower() + transformed = _LONG_CASEFOLDINGS.subn( + _multi_char_case_change, transformed)[0] + transformed = _replace_conditional(match, transformed) + return unescape(fill_in_whitespace(transformed)) + +# flag used to display only one time the lack of unidecode +UNIDECODE_ALERT_RAISED = False +class TextObjectTransformation(object): + """Base class for Transformations and ${VISUAL}.""" + + def __init__(self, token): + self._convert_to_ascii = False + + self._find = None + if token.search is None: + return + + flags = 0 + self._match_this_many = 1 + if token.options: + if "g" in token.options: + self._match_this_many = 0 + if "i" in token.options: + flags |= re.IGNORECASE + if "a" in token.options: + self._convert_to_ascii = True + + self._find = re.compile(token.search, flags | re.DOTALL) + self._replace = _CleverReplace(token.replace) + + def _transform(self, text): + """Do the actual transform on the given text.""" + global UNIDECODE_ALERT_RAISED # pylint:disable=global-statement + if self._convert_to_ascii: + try: + import unidecode + text = unidecode.unidecode(text) + except Exception: # pylint:disable=broad-except + if UNIDECODE_ALERT_RAISED == False: + UNIDECODE_ALERT_RAISED = True + sys.stderr.write( + "Please install unidecode python package in order to " + "be able to make ascii conversions.\n") + if self._find is None: + return text + return self._find.subn( + self._replace.replace, text, self._match_this_many)[0] + +class Transformation(Mirror, TextObjectTransformation): + """See module docstring.""" + + def __init__(self, parent, ts, token): + Mirror.__init__(self, parent, ts, token) + TextObjectTransformation.__init__(self, token) + + def _get_text(self): + return self._transform(self._ts.current_text) diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_viml_code.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_viml_code.py new file mode 100644 index 0000000..9370b2a --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_viml_code.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Implements `!v ` VimL interpolation.""" + +from UltiSnips import _vim +from UltiSnips.text_objects._base import NoneditableTextObject + +class VimLCode(NoneditableTextObject): + """See module docstring.""" + def __init__(self, parent, token): + self._code = token.code.replace("\\`", "`").strip() + + NoneditableTextObject.__init__(self, parent, token) + + def _update(self, done): + self.overwrite(_vim.eval(self._code)) + return True diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_visual.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_visual.py new file mode 100644 index 0000000..f4275c3 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/text_objects/_visual.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""A ${VISUAL} placeholder that will use the text that was last visually +selected and insert it here. If there was no text visually selected, this will +be the empty string. """ + +import re +import textwrap + +from UltiSnips import _vim +from UltiSnips.indent_util import IndentUtil +from UltiSnips.text_objects._transformation import TextObjectTransformation +from UltiSnips.text_objects._base import NoneditableTextObject + +_REPLACE_NON_WS = re.compile(r"[^ \t]") +class Visual(NoneditableTextObject, TextObjectTransformation): + """See module docstring.""" + + def __init__(self, parent, token): + # Find our containing snippet for visual_content + snippet = parent + while snippet: + try: + self._text = snippet.visual_content.text + self._mode = snippet.visual_content.mode + break + except AttributeError: + snippet = snippet._parent # pylint:disable=protected-access + if not self._text: + self._text = token.alternative_text + self._mode = "v" + + NoneditableTextObject.__init__(self, parent, token) + TextObjectTransformation.__init__(self, token) + + def _update(self, done): + if self._mode == "v": # Normal selection. + text = self._text + else: # Block selection or line selection. + text_before = _vim.buf[self.start.line][:self.start.col] + indent = _REPLACE_NON_WS.sub(" ", text_before) + iu = IndentUtil() + indent = iu.indent_to_spaces(indent) + indent = iu.spaces_to_indent(indent) + text = "" + for idx, line in enumerate(textwrap.dedent( + self._text).splitlines(True)): + if idx != 0: + text += indent + text += line + text = text[:-1] # Strip final '\n' + + text = self._transform(text) + self.overwrite(text) + self._parent._del_child(self) # pylint:disable=protected-access + + return True diff --git a/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/vim_state.py b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/vim_state.py new file mode 100644 index 0000000..28b7181 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/pythonx/UltiSnips/vim_state.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# encoding: utf-8 + +"""Some classes to conserve Vim's state for comparing over time.""" + +from collections import deque + +from UltiSnips import _vim +from UltiSnips.compatibility import as_unicode, byte2col +from UltiSnips.position import Position + +class VimPosition(Position): + """Represents the current position in the buffer, together with some status + variables that might change our decisions down the line.""" + + def __init__(self): + pos = _vim.buf.cursor + self._mode = _vim.eval("mode()") + Position.__init__(self, pos.line, pos.col) + + @property + def mode(self): + """Returns the mode() this position was created.""" + return self._mode + +class VimState(object): + """Caches some state information from Vim to better guess what editing + tasks the user might have done in the last step.""" + + def __init__(self): + self._poss = deque(maxlen=5) + self._lvb = None + + self._text_to_expect = None + self._unnamed_reg_cache = None + self._unnamed_reg_cached = False + + def remember_unnamed_register(self, text_to_expect): + """Save the unnamed register. 'text_to_expect' is text that we expect + to be contained in the register the next time this method is called - + this could be text from the tabstop that was selected and might have + been overwritten. We will not cash that then.""" + self._unnamed_reg_cached = True + unnamed_reg = _vim.eval('@"') + if unnamed_reg != self._text_to_expect: + self._unnamed_reg_cache = unnamed_reg + self._text_to_expect = text_to_expect + + def restore_unnamed_register(self): + """Restores the unnamed register and forgets what we cached.""" + if not self._unnamed_reg_cached: + return + escaped_cache = self._unnamed_reg_cache.replace("'", "''") + _vim.command("let @\"='%s'" % escaped_cache) + self._unnamed_reg_cached = False + + def remember_position(self): + """Remember the current position as a previous pose.""" + self._poss.append(VimPosition()) + + def remember_buffer(self, to): + """Remember the content of the buffer and the position.""" + self._lvb = _vim.buf[to.start.line:to.end.line+1] + self._lvb_len = len(_vim.buf) + self.remember_position() + + @property + def diff_in_buffer_length(self): + """Returns the difference in the length of the current buffer compared + to the remembered.""" + return len(_vim.buf) - self._lvb_len + + @property + def pos(self): + """The last remembered position.""" + return self._poss[-1] + + @property + def ppos(self): + """The second to last remembered position.""" + return self._poss[-2] + + @property + def remembered_buffer(self): + """The content of the remembered buffer.""" + return self._lvb[:] + +class VisualContentPreserver(object): + """Saves the current visual selection and the selection mode it was done in + (e.g. line selection, block selection or regular selection.)""" + + def __init__(self): + self.reset() + + def reset(self): + """Forget the preserved state.""" + self._mode = "" + self._text = as_unicode("") + + def conserve(self): + """Save the last visual selection ond the mode it was made in.""" + sl, sbyte = map(int, + (_vim.eval("""line("'<")"""), _vim.eval("""col("'<")"""))) + el, ebyte = map(int, + (_vim.eval("""line("'>")"""), _vim.eval("""col("'>")"""))) + sc = byte2col(sl, sbyte - 1) + ec = byte2col(el, ebyte - 1) + self._mode = _vim.eval("visualmode()") + + _vim_line_with_eol = lambda ln: _vim.buf[ln] + '\n' + + if sl == el: + text = _vim_line_with_eol(sl-1)[sc:ec+1] + else: + text = _vim_line_with_eol(sl-1)[sc:] + for cl in range(sl, el-1): + text += _vim_line_with_eol(cl) + text += _vim_line_with_eol(el-1)[:ec+1] + self._text = text + + @property + def text(self): + """The conserved text.""" + return self._text + + @property + def mode(self): + """The conserved visualmode().""" + return self._mode diff --git a/vim/vim.symlink/bundle/ultisnips/syntax/snippets.vim b/vim/vim.symlink/bundle/ultisnips/syntax/snippets.vim new file mode 100644 index 0000000..aa2da1b --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/syntax/snippets.vim @@ -0,0 +1,208 @@ +" Syntax highlighting for snippet files (used for UltiSnips.vim) +" Revision: 26/03/11 19:53:33 + +if exists("b:current_syntax") + finish +endif + +if expand("%:p:h:t") == "snippets" && search("^endsnippet", "nw") == 0 + \ && !exists("b:ultisnips_override_snipmate") + " this appears to be a snipmate file + " It's in a directory called snippets/ and there's no endsnippet keyword + " anywhere in the file. + source :h/snippets_snipmate.vim + finish +endif + +" Embedded Syntaxes {{{1 + +try + syntax include @Python syntax/python.vim + unlet b:current_syntax + syntax include @Viml syntax/vim.vim + unlet b:current_syntax + syntax include @Shell syntax/sh.vim + unlet b:current_syntax +catch /E403/ + " Ignore errors about syntax files that can't be loaded more than once +endtry + +" Syntax definitions {{{1 + +" Comments {{{2 + +syn match snipComment "^#.*" contains=snipTODO display +syn keyword snipTODO contained display FIXME NOTE NOTES TODO XXX + +" Errors {{{2 + +syn match snipLeadingSpaces "^\t* \+" contained + +" Extends {{{2 + +syn match snipExtends "^extends\%(\s.*\|$\)" contains=snipExtendsKeyword display +syn match snipExtendsKeyword "^extends" contained display + +" Definitions {{{2 + +" snippet {{{3 + +syn region snipSnippet start="^snippet\_s" end="^\zeendsnippet\s*$" contains=snipSnippetHeader nextgroup=snipSnippetFooter fold keepend +syn match snipSnippetHeader "^.*$" nextgroup=snipSnippetBody,snipSnippetFooter skipnl contained contains=snipSnippetHeaderKeyword +syn match snipSnippetHeaderKeyword "^snippet" contained nextgroup=snipSnippetTrigger skipwhite +syn region snipSnippetBody start="\_." end="^\zeendsnippet\s*$" contained contains=snipLeadingSpaces,@snipTokens +syn match snipSnippetFooter "^endsnippet.*" contained contains=snipSnippetFooterKeyword +syn match snipSnippetFooterKeyword "^endsnippet" contained + +" The current parser is a bit lax about parsing. For example, given this: +" snippet foo"bar" +" it treats `foo"bar"` as the trigger. But with this: +" snippet foo"bar baz" +" it treats `foo` as the trigger and "bar baz" as the description. +" I think this is an accident. Instead, we'll assume the description must +" be surrounded by spaces. That means we'll treat +" snippet foo"bar" +" as a trigger `foo"bar"` and +" snippet foo"bar baz" +" as an attempted multiword snippet `foo"bar baz"` that is invalid. +" NB: UltiSnips parses right-to-left, which Vim doesn't support, so that makes +" the following patterns very complicated. +syn match snipSnippetTrigger "\S\+" contained nextgroup=snipSnippetDocString,snipSnippetTriggerInvalid skipwhite +" We want to match a trailing " as the start of a doc comment, but we also +" want to allow for using " as the delimiter in a multiword/pattern snippet. +" So we have to define this twice, once in the general case that matches a +" trailing " as the doc comment, and once for the case of the multiword +" delimiter using " that has more constraints +syn match snipSnippetTrigger ,\([^"[:space:]]\).\{-}\1\%(\s*$\)\@!\ze\%(\s\+"[^"]*\%("\s\+[^"[:space:]]\+\|"\)\=\)\=\s*$, contained nextgroup=snipSnippetDocString skipwhite +syn match snipSnippetTrigger ,".\{-}"\ze\%(\s\+"\%(\s*\S\)\@=[^"]*\%("\s\+[^"[:space:]]\+\|"\)\=\)\=\s*$, contained nextgroup=snipSnippetDocString skipwhite +syn match snipSnippetTriggerInvalid ,\S\@=.\{-}\S\ze\%(\s\+"[^"]*\%("\s\+[^"[:space:]]\+\s*\|"\s*\)\=\|\s*\)$, contained nextgroup=snipSnippetDocString skipwhite +syn match snipSnippetDocString ,"[^"]*\%("\ze\s*\%(\s[^"[:space:]]\+\s*\)\=\)\=$, contained nextgroup=snipSnippetOptions skipwhite +syn match snipSnippetOptions ,\S\+, contained contains=snipSnippetOptionFlag +syn match snipSnippetOptionFlag ,[biwrts], contained + +" Command substitution {{{4 + +syn region snipCommand keepend matchgroup=snipCommandDelim start="`" skip="\\[{}\\$`]" end="`" contained contains=snipPythonCommand,snipVimLCommand,snipShellCommand,snipCommandSyntaxOverride +syn region snipShellCommand start="\ze\_." skip="\\[{}\\$`]" end="\ze`" contained contains=@Shell +syn region snipPythonCommand matchgroup=snipPythonCommandP start="`\@<=!p\_s" skip="\\[{}\\$`]" end="\ze`" contained contains=@Python +syn region snipVimLCommand matchgroup=snipVimLCommandV start="`\@<=!v\_s" skip="\\[{}\\$`]" end="\ze`" contained contains=@Viml +syn cluster snipTokens add=snipCommand +syn cluster snipTabStopTokens add=snipCommand + +" unfortunately due to the balanced braces parsing of commands, if a { occurs +" in the command, we need to prevent the embedded syntax highlighting. +" Otherwise, we can't track the balanced braces properly. + +syn region snipCommandSyntaxOverride start="\%(\\[{}\\$`]\|\_[^`"{]\)*\ze{" skip="\\[{}\\$`]" end="\ze`" contained contains=snipBalancedBraces transparent + +" Tab Stops {{{4 + +syn match snipEscape "\\[{}\\$`]" contained +syn cluster snipTokens add=snipEscape +syn cluster snipTabStopTokens add=snipEscape + +syn match snipMirror "\$\d\+" contained +syn cluster snipTokens add=snipMirror +syn cluster snipTabStopTokens add=snipMirror + +syn region snipTabStop matchgroup=snipTabStop start="\${\d\+[:}]\@=" end="}" contained contains=snipTabStopDefault extend +syn region snipTabStopDefault matchgroup=snipTabStop start=":" skip="\\[{}]" end="\ze}" contained contains=snipTabStopEscape,snipBalancedBraces,@snipTabStopTokens keepend +syn match snipTabStopEscape "\\[{}]" contained +syn region snipBalancedBraces start="{" end="}" contained transparent extend +syn cluster snipTokens add=snipTabStop +syn cluster snipTabStopTokens add=snipTabStop + +syn region snipVisual matchgroup=snipVisual start="\${VISUAL[:}/]\@=" end="}" contained contains=snipVisualDefault,snipTransformationPattern +syn region snipVisualDefault matchgroup=snipVisual start=":" end="\ze[}/]" contained contains=snipTabStopEscape nextgroup=snipTransformationPattern +syn cluster snipTokens add=snipVisual +syn cluster snipTabStopTokens add=snipVisual + +syn region snipTransformation matchgroup=snipTransformation start="\${\d\/\@=" end="}" contained contains=snipTransformationPattern +syn region snipTransformationPattern matchgroup=snipTransformationPatternDelim start="/" end="\ze/" contained contains=snipTransformationEscape nextgroup=snipTransformationReplace skipnl +syn region snipTransformationReplace matchgroup=snipTransformationPatternDelim start="/" end="/" contained contains=snipTransformationEscape nextgroup=snipTransformationOptions skipnl +syn region snipTransformationOptions start="\ze[^}]" end="\ze}" contained contains=snipTabStopEscape +syn match snipTransformationEscape "\\/" contained +syn cluster snipTokens add=snipTransformation +syn cluster snipTabStopTokens add=snipTransformation + +" global {{{3 + +" Generic (non-Python) {{{4 + +syn region snipGlobal start="^global\_s" end="^\zeendglobal\s*$" contains=snipGlobalHeader nextgroup=snipGlobalFooter fold keepend +syn match snipGlobalHeader "^.*$" nextgroup=snipGlobalBody,snipGlobalFooter skipnl contained contains=snipGlobalHeaderKeyword +syn region snipGlobalBody start="\_." end="^\zeendglobal\s*$" contained contains=snipLeadingSpaces + +" Python (!p) {{{4 + +syn region snipGlobal start=,^global\s\+!p\%(\s\+"[^"]*\%("\s\+[^"[:space:]]\+\|"\)\=\)\=\s*$, end=,^\zeendglobal\s*$, contains=snipGlobalPHeader nextgroup=snipGlobalFooter fold keepend +syn match snipGlobalPHeader "^.*$" nextgroup=snipGlobalPBody,snipGlobalFooter skipnl contained contains=snipGlobalHeaderKeyword +syn match snipGlobalHeaderKeyword "^global" contained nextgroup=snipSnippetTrigger skipwhite +syn region snipGlobalPBody start="\_." end="^\zeendglobal\s*$" contained contains=@Python + +" Common {{{4 + +syn match snipGlobalFooter "^endglobal.*" contained contains=snipGlobalFooterKeyword +syn match snipGlobalFooterKeyword "^endglobal" contained + +" priority {{{3 + +syn match snipPriority "^priority\%(\s.*\|$\)" contains=snipPriorityKeyword display +syn match snipPriorityKeyword "^priority" contained nextgroup=snipPriorityValue skipwhite display +syn match snipPriorityValue "-\?\d\+" contained display + +" Snippt Clearing {{{2 + +syn match snipClear "^clearsnippets\%(\s.*\|$\)" contains=snipClearKeyword display +syn match snipClearKeyword "^clearsnippets" contained display + +" Highlight groups {{{1 + +hi def link snipComment Comment +hi def link snipTODO Todo +hi def snipLeadingSpaces term=reverse ctermfg=15 ctermbg=4 gui=reverse guifg=#dc322f + +hi def link snipKeyword Keyword + +hi def link snipExtendsKeyword snipKeyword + +hi def link snipSnippetHeaderKeyword snipKeyword +hi def link snipSnippetFooterKeyword snipKeyword + +hi def link snipSnippetTrigger Identifier +hi def link snipSnippetTriggerInvalid Error +hi def link snipSnippetDocString String +hi def link snipSnippetOptionFlag Special + +hi def link snipGlobalHeaderKeyword snipKeyword +hi def link snipGlobalFooterKeyword snipKeyword + +hi def link snipCommand Special +hi def link snipCommandDelim snipCommand +hi def link snipShellCommand snipCommand +hi def link snipVimLCommand snipCommand +hi def link snipPythonCommandP PreProc +hi def link snipVimLCommandV PreProc + +hi def link snipEscape Special +hi def link snipMirror StorageClass +hi def link snipTabStop Define +hi def link snipTabStopDefault String +hi def link snipTabStopEscape Special +hi def link snipVisual snipTabStop +hi def link snipVisualDefault snipTabStopDefault +hi def link snipTransformation snipTabStop +hi def link snipTransformationPattern String +hi def link snipTransformationPatternDelim Operator +hi def link snipTransformationReplace String +hi def link snipTransformationEscape snipEscape +hi def link snipTransformationOptions Operator + +hi def link snipPriorityKeyword Keyword +hi def link snipPriorityValue Number + +hi def link snipClearKeyword Keyword + +" }}}1 + +let b:current_syntax = "snippets" diff --git a/vim/vim.symlink/bundle/ultisnips/syntax/snippets_snipmate.vim b/vim/vim.symlink/bundle/ultisnips/syntax/snippets_snipmate.vim new file mode 100644 index 0000000..aa55c1f --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/syntax/snippets_snipmate.vim @@ -0,0 +1,47 @@ +" Syntax highlighting variant used for snipmate snippets files +" The snippets.vim file sources this if it wants snipmate mode + +if exists("b:current_syntax") + finish +endif + +" Embedded syntaxes {{{1 + +" Re-include the original file so we can share some of its definitions +let b:ultisnips_override_snipmate = 1 +syn include :h/snippets.vim +unlet b:current_syntax +unlet b:ultisnips_override_snipmate + +syn cluster snipTokens contains=snipEscape,snipVisual,snipTabStop,snipMirror,snipmateCommand +syn cluster snipTabStopTokens contains=snipVisual,snipMirror,snipEscape,snipmateCommand + +" Syntax definitions {{{1 + +syn match snipmateComment "^#.*" + +syn match snipmateExtends "^extends\%(\s.*\|$\)" contains=snipExtendsKeyword display + +syn region snipmateSnippet start="^snippet\ze\%(\s\|$\)" end="^\ze[^[:tab:]]" contains=snipmateSnippetHeader keepend +syn match snipmateSnippetHeader "^.*" contained contains=snipmateKeyword nextgroup=snipmateSnippetBody skipnl skipempty +syn match snipmateKeyword "^snippet\ze\%(\s\|$\)" contained nextgroup=snipmateTrigger skipwhite +syn match snipmateTrigger "\S\+" contained nextgroup=snipmateDescription skipwhite +syn match snipmateDescription "\S.*" contained +syn region snipmateSnippetBody start="^\t" end="^\ze[^[:tab:]]" contained contains=@snipTokens + +syn region snipmateCommand keepend matchgroup=snipCommandDelim start="`" skip="\\[{}\\$`]" end="`" contained contains=snipCommandSyntaxOverride,@Viml + +" Highlight groups {{{1 + +hi def link snipmateComment snipComment + +hi def link snipmateSnippet snipSnippet +hi def link snipmateKeyword snipKeyword +hi def link snipmateTrigger snipSnippetTrigger +hi def link snipmateDescription snipSnippetDocString + +hi def link snipmateCommand snipCommand + +" }}}1 + +let b:current_syntax = "snippets" diff --git a/vim/vim.symlink/bundle/ultisnips/test/__init__.py b/vim/vim.symlink/bundle/ultisnips/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/vim/vim.symlink/bundle/ultisnips/test/constant.py b/vim/vim.symlink/bundle/ultisnips/test/constant.py new file mode 100644 index 0000000..fcfe14a --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/constant.py @@ -0,0 +1,24 @@ +import sys + +# Some constants for better reading +BS = '\x7f' +ESC = '\x1b' +ARR_L = '\x1bOD' +ARR_R = '\x1bOC' +ARR_U = '\x1bOA' +ARR_D = '\x1bOB' + +# multi-key sequences generating a single key press +SEQUENCES = [ARR_L, ARR_R, ARR_U, ARR_D] + +# Defined Constants +JF = "?" # Jump forwards +JB = "+" # Jump backwards +LS = "@" # List snippets +EX = "\t" # EXPAND +EA = "#" # Expand anonymous + +COMPL_KW = chr(24) + chr(14) +COMPL_ACCEPT = chr(25) + +PYTHON3 = sys.version_info >= (3,0) diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_AnonymousExpansion.py b/vim/vim.symlink/bundle/ultisnips/test/test_AnonymousExpansion.py new file mode 100644 index 0000000..7a361c9 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_AnonymousExpansion.py @@ -0,0 +1,54 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Anonymous Expansion {{{# +class _AnonBase(_VimTest): + args = "" + def _extra_options_pre_init(self, vim_config): + vim_config.append("inoremap %s =UltiSnips#Anon(%s)" + % (EA, self.args)) + +class Anon_NoTrigger_Simple(_AnonBase): + args = '"simple expand"' + keys = "abc" + EA + wanted = "abcsimple expand" + +class Anon_NoTrigger_AfterSpace(_AnonBase): + args = '"simple expand"' + keys = "abc " + EA + wanted = "abc simple expand" + +class Anon_NoTrigger_BeginningOfLine(_AnonBase): + args = r"':latex:\`$1\`$0'" + keys = EA + "Hello" + JF + "World" + wanted = ":latex:`Hello`World" +class Anon_NoTrigger_FirstCharOfLine(_AnonBase): + args = r"':latex:\`$1\`$0'" + keys = " " + EA + "Hello" + JF + "World" + wanted = " :latex:`Hello`World" + +class Anon_NoTrigger_Multi(_AnonBase): + args = '"simple $1 expand $1 $0"' + keys = "abc" + EA + "123" + JF + "456" + wanted = "abcsimple 123 expand 123 456" + +class Anon_Trigger_Multi(_AnonBase): + args = '"simple $1 expand $1 $0", "abc"' + keys = "123 abc" + EA + "123" + JF + "456" + wanted = "123 simple 123 expand 123 456" + +class Anon_Trigger_Simple(_AnonBase): + args = '"simple expand", "abc"' + keys = "abc" + EA + wanted = "simple expand" + +class Anon_Trigger_Twice(_AnonBase): + args = '"simple expand", "abc"' + keys = "abc" + EA + "\nabc" + EX + wanted = "simple expand\nabc" + EX + +class Anon_Trigger_Opts(_AnonBase): + args = '"simple expand", ".*abc", "desc", "r"' + keys = "blah blah abc" + EA + wanted = "simple expand" +# End: Anonymous Expansion #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Chars.py b/vim/vim.symlink/bundle/ultisnips/test/test_Chars.py new file mode 100644 index 0000000..752bd62 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Chars.py @@ -0,0 +1,196 @@ +# encoding: utf-8 +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * +from test.util import running_on_windows + +# Quotes in Snippets {{{# +# Test for Bug #774917 +def _snip_quote(qt): + return ( + ("te" + qt + "st", "Expand me" + qt + "!", "test: "+qt), + ("te", "Bad", ""), + ) + +class Snippet_With_SingleQuote(_VimTest): + snippets = _snip_quote("'") + keys = "te'st" + EX + wanted = "Expand me'!" + +class Snippet_With_SingleQuote_List(_VimTest): + snippets = _snip_quote("'") + keys = "te" + LS + "2\n" + wanted = "Expand me'!" + +class Snippet_With_DoubleQuote(_VimTest): + snippets = _snip_quote('"') + keys = 'te"st' + EX + wanted = "Expand me\"!" + +class Snippet_With_DoubleQuote_List(_VimTest): + snippets = _snip_quote('"') + keys = "te" + LS + "2\n" + wanted = "Expand me\"!" + +# End: Quotes in Snippets #}}} + +# Trailing whitespace {{{# +class RemoveTrailingWhitespace(_VimTest): + snippets = ("test", """Hello\t ${1:default}\n$2""", "", "s") + wanted = """Hello\nGoodbye""" + keys = "test" + EX + BS + JF + "Goodbye" +class LeaveTrailingWhitespace(_VimTest): + snippets = ("test", """Hello \t ${1:default}\n$2""") + wanted = """Hello \t \nGoodbye""" + keys = "test" + EX + BS + JF + "Goodbye" +# End: Trailing whitespace #}}} + +# Newline in default text {{{# +# Tests for bug 616315 # +class TrailingNewline_TabStop_NLInsideStuffBehind(_VimTest): + snippets = ("test", r""" +x${1: +}<-behind1 +$2<-behind2""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj<-behind1 +k<-behind2""" + +class TrailingNewline_TabStop_JustNL(_VimTest): + snippets = ("test", r""" +x${1: +} +$2""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj +k""" + +class TrailingNewline_TabStop_EndNL(_VimTest): + snippets = ("test", r""" +x${1:a +} +$2""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj +k""" + +class TrailingNewline_TabStop_StartNL(_VimTest): + snippets = ("test", r""" +x${1: +a} +$2""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj +k""" + +class TrailingNewline_TabStop_EndStartNL(_VimTest): + snippets = ("test", r""" +x${1: +a +} +$2""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj +k""" + +class TrailingNewline_TabStop_NotEndStartNL(_VimTest): + snippets = ("test", r""" +x${1:a +a} +$2""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj +k""" + +class TrailingNewline_TabStop_ExtraNL_ECR(_VimTest): + snippets = ("test", r""" +x${1:a +a} +$2 +""") + keys = "test" + EX + "j" + JF + "k" + wanted = """ +xj +k +""" + +class _MultiLineDefault(_VimTest): + snippets = ("test", r""" +x${1:a +b +c +d +e +f} +$2""") + +class MultiLineDefault_Jump(_MultiLineDefault): + keys = "test" + EX + JF + "y" + wanted = """ +xa +b +c +d +e +f +y""" + +class MultiLineDefault_Type(_MultiLineDefault): + keys = "test" + EX + "z" + JF + "y" + wanted = """ +xz +y""" + +class MultiLineDefault_BS(_MultiLineDefault): + keys = "test" + EX + BS + JF + "y" + wanted = """ +x +y""" + +# End: Newline in default text #}}} + +# Umlauts and Special Chars {{{# +class _UmlautsBase(_VimTest): + skip_if = lambda self: running_on_windows() # SendKeys can't send UTF characters + +class Snippet_With_Umlauts_List(_UmlautsBase): + snippets = _snip_quote('ü') + keys = 'te' + LS + "2\n" + wanted = "Expand meü!" + +class Snippet_With_Umlauts(_UmlautsBase): + snippets = _snip_quote('ü') + keys = 'teüst' + EX + wanted = "Expand meü!" + +class Snippet_With_Umlauts_TypeOn(_UmlautsBase): + snippets = ('ül', 'üüüüüßßßß') + keys = 'te ül' + EX + "more text" + wanted = "te üüüüüßßßßmore text" +class Snippet_With_Umlauts_OverwriteFirst(_UmlautsBase): + snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü') + keys = 'te ül' + EX + "more text" + JF + JF + "end" + wanted = "te üü more text üü helloßß\nüüüüend" +class Snippet_With_Umlauts_OverwriteSecond(_UmlautsBase): + snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü') + keys = 'te ül' + EX + JF + "more text" + JF + "end" + wanted = "te üü world üü more textßß\nüüüüend" +class Snippet_With_Umlauts_OverwriteNone(_UmlautsBase): + snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü') + keys = 'te ül' + EX + JF + JF + "end" + wanted = "te üü world üü helloßß\nüüüüend" +class Snippet_With_Umlauts_Mirrors(_UmlautsBase): + snippets = ('ül', 'üü ${1:world} üü $1') + keys = 'te ül' + EX + "hello" + wanted = "te üü hello üü hello" +class Snippet_With_Umlauts_Python(_UmlautsBase): + snippets = ('ül', 'üü ${1:world} üü `!p snip.rv = len(t[1])*"a"`') + keys = 'te ül' + EX + "hüüll" + wanted = "te üü hüüll üü aaaaa" +# End: Umlauts and Special Chars #}}} + diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Completion.py b/vim/vim.symlink/bundle/ultisnips/test/test_Completion.py new file mode 100644 index 0000000..3bbe079 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Completion.py @@ -0,0 +1,30 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Tab Completion of Words {{{# +class Completion_SimpleExample_ECR(_VimTest): + snippets = ("test", "$1 ${1:blah}") + keys = "superkallifragilistik\ntest" + EX + "sup" + COMPL_KW + \ + COMPL_ACCEPT + " some more" + wanted = "superkallifragilistik\nsuperkallifragilistik some more " \ + "superkallifragilistik some more" + +# We need >2 different words with identical starts to create the +# popup-menu: +COMPLETION_OPTIONS = "completion1\ncompletion2\n" + +class Completion_ForwardsJumpWithoutCOMPL_ACCEPT(_VimTest): + # completions should not be truncated when JF is activated without having + # pressed COMPL_ACCEPT (Bug #598903) + snippets = ("test", "$1 $2") + keys = COMPLETION_OPTIONS + "test" + EX + "com" + COMPL_KW + JF + "foo" + wanted = COMPLETION_OPTIONS + "completion1 foo" + +class Completion_BackwardsJumpWithoutCOMPL_ACCEPT(_VimTest): + # completions should not be truncated when JB is activated without having + # pressed COMPL_ACCEPT (Bug #598903) + snippets = ("test", "$1 $2") + keys = COMPLETION_OPTIONS + "test" + EX + "foo" + JF + "com" + COMPL_KW + \ + JB + "foo" + wanted = COMPLETION_OPTIONS + "foo completion1" +# End: Tab Completion of Words #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Editing.py b/vim/vim.symlink/bundle/ultisnips/test/test_Editing.py new file mode 100644 index 0000000..58e7288 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Editing.py @@ -0,0 +1,64 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Undo of Snippet insertion {{{# +class Undo_RemoveMultilineSnippet(_VimTest): + snippets = ("test", "Hello\naaa ${1} bbb\nWorld") + keys = "test" + EX + ESC + "u" + "inothing" + wanted = "nothing" +class Undo_RemoveEditInTabstop(_VimTest): + snippets = ("test", "$1 Hello\naaa ${1} bbb\nWorld") + keys = "hello test" + EX + "upsi" + ESC + "hh" + "iabcdef" + ESC + "u" + wanted = "hello upsi Hello\naaa upsi bbb\nWorld" +class Undo_RemoveWholeSnippet(_VimTest): + snippets = ("test", "Hello\n${1:Hello}World") + keys = "first line\n\n\n\n\n\nthird line" + \ + ESC + "3k0itest" + EX + ESC + "uiupsy" + wanted = "first line\n\n\nupsy\n\n\nthird line" +class JumpForward_DefSnippet(_VimTest): + snippets = ("test", "${1}\n`!p snip.rv = '\\n'.join(t[1].split())`\n\n${0:pass}") + keys = "test" + EX + "a b c" + JF + "shallnot" + wanted = "a b c\na\nb\nc\n\nshallnot" +class DeleteSnippetInsertion0(_VimTest): + snippets = ("test", "${1:hello} $1") + keys = "test" + EX + ESC + "Vkx" + "i\nworld\n" + wanted = "world" +class DeleteSnippetInsertion1(_VimTest): + snippets = ("test", r"$1${1/(.*)/(?0::.)/}") + keys = "test" + EX + ESC + "u" + "i" + JF + "\t" + wanted = "\t" +# End: Undo of Snippet insertion #}}} + +# Normal mode editing {{{# +# Test for bug #927844 +class DeleteLastTwoLinesInSnippet(_VimTest): + snippets = ("test", "$1hello\nnice\nworld") + keys = "test" + EX + ESC + "j2dd" + wanted = "hello" +class DeleteCurrentTabStop1_JumpBack(_VimTest): + snippets = ("test", "${1:hi}\nend") + keys = "test" + EX + ESC + "ddi" + JB + wanted = "end" +class DeleteCurrentTabStop2_JumpBack(_VimTest): + snippets = ("test", "${1:hi}\n${2:world}\nend") + keys = "test" + EX + JF + ESC + "ddi" + JB + "hello" + wanted = "hello\nend" +class DeleteCurrentTabStop3_JumpAround(_VimTest): + snippets = ("test", "${1:hi}\n${2:world}\nend") + keys = "test" + EX + JF + ESC + "ddkji" + JB + "hello" + JF + "world" + wanted = "hello\nendworld" + +# End: Normal mode editing #}}} + +# Pressing BS in TabStop {{{# +# Test for Bug #774917 +class Backspace_TabStop_Zero(_VimTest): + snippets = ("test", "A${1:C} ${0:DDD}", "This is Case 1") + keys = "test" + EX + "A" + JF + BS + "BBB" + wanted = "AA BBB" + +class Backspace_TabStop_NotZero(_VimTest): + snippets = ("test", "A${1:C} ${2:DDD}", "This is Case 1") + keys = "test" + EX + "A" + JF + BS + "BBB" + wanted = "AA BBB" +# End: Pressing BS in TabStop #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Expand.py b/vim/vim.symlink/bundle/ultisnips/test/test_Expand.py new file mode 100644 index 0000000..e61464f --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Expand.py @@ -0,0 +1,55 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Simple Expands {{{# +class _SimpleExpands(_VimTest): + snippets = ("hallo", "Hallo Welt!") + +class SimpleExpand_ExpectCorrectResult(_SimpleExpands): + keys = "hallo" + EX + wanted = "Hallo Welt!" +class SimpleExpandTwice_ExpectCorrectResult(_SimpleExpands): + keys = "hallo" + EX + '\nhallo' + EX + wanted = "Hallo Welt!\nHallo Welt!" + +class SimpleExpandNewLineAndBackspae_ExpectCorrectResult(_SimpleExpands): + keys = "hallo" + EX + "\nHallo Welt!\n\n\b\b\b\b\b" + wanted = "Hallo Welt!\nHallo We" + def _extra_options_pre_init(self, vim_config): + vim_config.append("set backspace=eol,start") + +class SimpleExpandTypeAfterExpand_ExpectCorrectResult(_SimpleExpands): + keys = "hallo" + EX + "and again" + wanted = "Hallo Welt!and again" + +class SimpleExpandTypeAndDelete_ExpectCorrectResult(_SimpleExpands): + keys = "na du hallo" + EX + "and again\b\b\b\b\bblub" + wanted = "na du Hallo Welt!and blub" + +class DoNotExpandAfterSpace_ExpectCorrectResult(_SimpleExpands): + keys = "hallo " + EX + wanted = "hallo " + EX + +class ExitSnippetModeAfterTabstopZero(_VimTest): + snippets = ("test", "SimpleText") + keys = "test" + EX + EX + wanted = "SimpleText" + EX + +class ExpandInTheMiddleOfLine_ExpectCorrectResult(_SimpleExpands): + keys = "Wie hallo gehts" + ESC + "bhi" + EX + wanted = "Wie Hallo Welt! gehts" +class MultilineExpand_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "Hallo Welt!\nUnd Wie gehts") + keys = "Wie hallo gehts" + ESC + "bhi" + EX + wanted = "Wie Hallo Welt!\nUnd Wie gehts gehts" +class MultilineExpandTestTyping_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "Hallo Welt!\nUnd Wie gehts") + wanted = "Wie Hallo Welt!\nUnd Wie gehtsHuiui! gehts" + keys = "Wie hallo gehts" + ESC + "bhi" + EX + "Huiui!" +class SimpleExpandEndingWithNewline_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "Hallo Welt\n") + keys = "hallo" + EX + "\nAnd more" + wanted = "Hallo Welt\n\nAnd more" + + +# End: Simple Expands #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Fixes.py b/vim/vim.symlink/bundle/ultisnips/test/test_Fixes.py new file mode 100644 index 0000000..4c4ee80 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Fixes.py @@ -0,0 +1,46 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Test for bug 1251994 {{{# +class Bug1251994(_VimTest): + snippets = ("test", "${2:#2} ${1:#1};$0") + keys = " test" + EX + "hello" + JF + "world" + JF + "blub" + wanted = " world hello;blub" +# End: 1251994 #}}} + +# Test for https://github.com/SirVer/ultisnips/issues/157 (virtualedit) {{{# +class VirtualEdit(_VimTest): + snippets = ("pd", "padding: ${1:0}px") + keys = "\t\t\tpd" + EX + "2" + wanted = "\t\t\tpadding: 2px" + + def _extra_options_pre_init(self, vim_config): + vim_config.append('set virtualedit=all') + vim_config.append('set noexpandtab') +# End: 1251994 #}}} + +# Test for Github Pull Request #134 - Retain unnamed register {{{# +class RetainsTheUnnamedRegister(_VimTest): + snippets = ("test", "${1:hello} ${2:world} ${0}") + keys = "yank" + ESC + "by4lea test" + EX + "HELLO" + JF + JF + ESC + "p" + wanted = "yank HELLO world yank" +class RetainsTheUnnamedRegister_ButOnlyOnce(_VimTest): + snippets = ("test", "${1:hello} ${2:world} ${0}") + keys = "blahfasel" + ESC + "v" + 4*ARR_L + "xotest" + EX + ESC + ARR_U + "v0xo" + ESC + "p" + wanted = "\nblah\nhello world " +# End: Github Pull Request # 134 #}}} + +# Test to ensure that shiftwidth follows tabstop when it's set to zero post +# version 7.3.693. Prior to that version a shiftwidth of zero effectively +# removes tabs. +class ShiftWidthZero(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config += [ + "if exists('*shiftwidth')", + " set shiftwidth=0", + "endif", + ] + snippets = ("test", "\t${1}${0}") + keys = "test" + EX + "foo" + wanted = "\tfoo" + diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Folding.py b/vim/vim.symlink/bundle/ultisnips/test/test_Folding.py new file mode 100644 index 0000000..bcc9659 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Folding.py @@ -0,0 +1,42 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Folding Interaction {{{# +class FoldingEnabled_SnippetWithFold_ExpectNoFolding(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set foldlevel=0") + vim_config.append("set foldmethod=marker") + snippets = ("test", r"""Hello {{{ +${1:Welt} }}}""") + keys = "test" + EX + "Ball" + wanted = """Hello {{{ +Ball }}}""" +class FoldOverwrite_Simple_ECR(_VimTest): + snippets = ("fold", +"""# ${1:Description} `!p snip.rv = vim.eval("&foldmarker").split(",")[0]` + +# End: $1 `!p snip.rv = vim.eval("&foldmarker").split(",")[1]`""") + keys = "fold" + EX + "hi" + wanted = "# hi {{{\n\n# End: hi }}}" +class Fold_DeleteMiddleLine_ECR(_VimTest): + snippets = ("fold", +"""# ${1:Description} `!p snip.rv = vim.eval("&foldmarker").split(",")[0]` + + +# End: $1 `!p snip.rv = vim.eval("&foldmarker").split(",")[1]`""") + keys = "fold" + EX + "hi" + ESC + "jdd" + wanted = "# hi {{{\n\n# End: hi }}}" + +class PerlSyntaxFold(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set foldlevel=0") + vim_config.append("syntax enable") + vim_config.append("set foldmethod=syntax") + vim_config.append("let g:perl_fold = 1") + vim_config.append("so $VIMRUNTIME/syntax/perl.vim") + snippets = ("test", r"""package ${1:`!v printf('c%02d', 3)`}; +${0} +1;""") + keys = "test" + EX + JF + "sub junk {}" + wanted = "package c03;\nsub junk {}\n1;" +# End: Folding Interaction #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Format.py b/vim/vim.symlink/bundle/ultisnips/test/test_Format.py new file mode 100644 index 0000000..619860f --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Format.py @@ -0,0 +1,131 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * +from test.util import running_on_windows + +# ExpandTab {{{# +class _ExpandTabs(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set expandtab") + +class RecTabStopsWithExpandtab_SimpleExample_ECR(_ExpandTabs): + snippets = ("m", "\tBlaahblah \t\t ") + keys = "m" + EX + wanted = " Blaahblah \t\t " + +class RecTabStopsWithExpandtab_SpecialIndentProblem_ECR(_ExpandTabs): + # Windows indents the Something line after pressing return, though it + # shouldn't because it contains a manual indent. All other vim versions do + # not do this. Windows vim does not interpret the changes made by :py as + # changes made 'manually', while the other vim version seem to do so. Since + # the fault is not with UltiSnips, we simply skip this test on windows + # completely. + skip_if = lambda self: running_on_windows() + snippets = ( + ("m1", "Something"), + ("m", "\t$0"), + ) + keys = "m" + EX + "m1" + EX + '\nHallo' + wanted = " Something\n Hallo" + def _extra_options_pre_init(self, vim_config): + _ExpandTabs._extra_options_pre_init(self, vim_config) + vim_config.append("set indentkeys=o,O,*,<>>,{,}") + vim_config.append("set indentexpr=8") +# End: ExpandTab #}}} + +# Proper Indenting {{{# +class ProperIndenting_SimpleCase_ECR(_VimTest): + snippets = ("test", "for\n blah") + keys = " test" + EX + "Hui" + wanted = " for\n blahHui" +class ProperIndenting_SingleLineNoReindenting_ECR(_VimTest): + snippets = ("test", "hui") + keys = " test" + EX + "blah" + wanted = " huiblah" +class ProperIndenting_AutoIndentAndNewline_ECR(_VimTest): + snippets = ("test", "hui") + keys = " test" + EX + "\n"+ "blah" + wanted = " hui\n blah" + def _extra_options_pre_init(self, vim_config): + vim_config.append("set autoindent") +# Test for bug 1073816 +class ProperIndenting_FirstLineInFile_ECR(_VimTest): + text_before = "" + text_after = "" + files = { "us/all.snippets": r""" +global !p +def complete(t, opts): + if t: + opts = [ m[len(t):] for m in opts if m.startswith(t) ] + if len(opts) == 1: + return opts[0] + elif len(opts) > 1: + return "(" + "|".join(opts) + ")" + else: + return "" +endglobal + +snippet '^#?inc' "#include <>" !r +#include <$1`!p snip.rv = complete(t[1], ['cassert', 'cstdio', 'cstdlib', 'cstring', 'fstream', 'iostream', 'sstream'])`> +endsnippet + """} + keys = "inc" + EX + "foo" + wanted = "#include " +class ProperIndenting_FirstLineInFileComplete_ECR(ProperIndenting_FirstLineInFile_ECR): + keys = "inc" + EX + "cstdl" + wanted = "#include " +# End: Proper Indenting #}}} + +# Format options tests {{{# +class _FormatoptionsBase(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set tw=20") + vim_config.append("set fo=lrqntc") + +class FOSimple_Break_ExpectCorrectResult(_FormatoptionsBase): + snippets = ("test", "${1:longer expand}\n$1\n$0", "", "f") + keys = "test" + EX + "This is a longer text that should wrap as formatoptions are enabled" + JF + "end" + wanted = "This is a longer\ntext that should\nwrap as\nformatoptions are\nenabled\n" + \ + "This is a longer\ntext that should\nwrap as\nformatoptions are\nenabled\n" + "end" + + +class FOTextBeforeAndAfter_ExpectCorrectResult(_FormatoptionsBase): + snippets = ("test", "Before${1:longer expand}After\nstart$1end") + keys = "test" + EX + "This is a longer text that should wrap" + wanted = \ +"""BeforeThis is a +longer text that +should wrapAfter +startThis is a +longer text that +should wrapend""" + + +# Tests for https://bugs.launchpad.net/bugs/719998 +class FOTextAfter_ExpectCorrectResult(_FormatoptionsBase): + snippets = ("test", "${1:longer expand}after\nstart$1end") + keys = ("test" + EX + "This is a longer snippet that should wrap properly " + "and the mirror below should work as well") + wanted = \ +"""This is a longer +snippet that should +wrap properly and +the mirror below +should work as wellafter +startThis is a longer +snippet that should +wrap properly and +the mirror below +should work as wellend""" + +class FOWrapOnLongWord_ExpectCorrectResult(_FormatoptionsBase): + snippets = ("test", "${1:longer expand}after\nstart$1end") + keys = ("test" + EX + "This is a longersnippet that should wrap properly") + wanted = \ +"""This is a +longersnippet that +should wrap properlyafter +startThis is a +longersnippet that +should wrap properlyend""" +# End: Format options tests #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Interpolation.py b/vim/vim.symlink/bundle/ultisnips/test/test_Interpolation.py new file mode 100644 index 0000000..09273d7 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Interpolation.py @@ -0,0 +1,375 @@ +# encoding: utf-8 +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * +from test.util import running_on_windows + +# ShellCode Interpolation {{{# +class TabStop_Shell_SimpleExample(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", "hi `echo hallo` you!") + keys = "test" + EX + "and more" + wanted = "hi hallo you!and more" +class TabStop_Shell_WithUmlauts(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", "hi `echo höüäh` you!") + keys = "test" + EX + "and more" + wanted = "hi höüäh you!and more" +class TabStop_Shell_TextInNextLine(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", "hi `echo hallo`\nWeiter") + keys = "test" + EX + "and more" + wanted = "hi hallo\nWeiterand more" +class TabStop_Shell_InDefValue_Leave(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", "Hallo ${1:now `echo fromecho`} end") + keys = "test" + EX + JF + "and more" + wanted = "Hallo now fromecho endand more" +class TabStop_Shell_InDefValue_Overwrite(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", "Hallo ${1:now `echo fromecho`} end") + keys = "test" + EX + "overwrite" + JF + "and more" + wanted = "Hallo overwrite endand more" +class TabStop_Shell_TestEscapedChars_Overwrite(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", r"""`echo \`echo "\\$hi"\``""") + keys = "test" + EX + wanted = "$hi" +class TabStop_Shell_TestEscapedCharsAndShellVars_Overwrite(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", r"""`hi="blah"; echo \`echo "$hi"\``""") + keys = "test" + EX + wanted = "blah" + +class TabStop_Shell_ShebangPython(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = ("test", """Hallo ${1:now `#!/usr/bin/env python +print "Hallo Welt" +`} end""") + keys = "test" + EX + JF + "and more" + wanted = "Hallo now Hallo Welt endand more" +# End: ShellCode Interpolation #}}} +# VimScript Interpolation {{{# +class TabStop_VimScriptInterpolation_SimpleExample(_VimTest): + snippets = ("test", """hi `!v indent(".")` End""") + keys = " test" + EX + wanted = " hi 4 End" +# End: VimScript Interpolation #}}} +# PythonCode Interpolation {{{# +# Deprecated Implementation {{{# +class PythonCodeOld_SimpleExample(_VimTest): + snippets = ("test", """hi `!p res = "Hallo"` End""") + keys = "test" + EX + wanted = "hi Hallo End" +class PythonCodeOld_ReferencePlaceholderAfter(_VimTest): + snippets = ("test", """${1:hi} `!p res = t[1]+".blah"` End""") + keys = "test" + EX + "ho" + wanted = "ho ho.blah End" +class PythonCodeOld_ReferencePlaceholderBefore(_VimTest): + snippets = ("test", """`!p res = len(t[1])*"#"`\n${1:some text}""") + keys = "test" + EX + "Hallo Welt" + wanted = "##########\nHallo Welt" +class PythonCodeOld_TransformedBeforeMultiLine(_VimTest): + snippets = ("test", """${1/.+/egal/m} ${1:`!p +res = "Hallo"`} End""") + keys = "test" + EX + wanted = "egal Hallo End" +class PythonCodeOld_IndentedMultiline(_VimTest): + snippets = ("test", """start `!p a = 1 +b = 2 +if b > a: + res = "b isbigger a" +else: + res = "a isbigger b"` end""") + keys = " test" + EX + wanted = " start b isbigger a end" +# End: Deprecated Implementation #}}} +# New Implementation {{{# +class PythonCode_UseNewOverOld(_VimTest): + snippets = ("test", """hi `!p res = "Old" +snip.rv = "New"` End""") + keys = "test" + EX + wanted = "hi New End" + +class PythonCode_SimpleExample(_VimTest): + snippets = ("test", """hi `!p snip.rv = "Hallo"` End""") + keys = "test" + EX + wanted = "hi Hallo End" + +class PythonCode_SimpleExample_ReturnValueIsEmptyString(_VimTest): + snippets = ("test", """hi`!p snip.rv = ""`End""") + keys = "test" + EX + wanted = "hiEnd" + +class PythonCode_ReferencePlaceholder(_VimTest): + snippets = ("test", """${1:hi} `!p snip.rv = t[1]+".blah"` End""") + keys = "test" + EX + "ho" + wanted = "ho ho.blah End" + +class PythonCode_ReferencePlaceholderBefore(_VimTest): + snippets = ("test", """`!p snip.rv = len(t[1])*"#"`\n${1:some text}""") + keys = "test" + EX + "Hallo Welt" + wanted = "##########\nHallo Welt" +class PythonCode_TransformedBeforeMultiLine(_VimTest): + snippets = ("test", """${1/.+/egal/m} ${1:`!p +snip.rv = "Hallo"`} End""") + keys = "test" + EX + wanted = "egal Hallo End" +class PythonCode_MultilineIndented(_VimTest): + snippets = ("test", """start `!p a = 1 +b = 2 +if b > a: + snip.rv = "b isbigger a" +else: + snip.rv = "a isbigger b"` end""") + keys = " test" + EX + wanted = " start b isbigger a end" + +class PythonCode_SimpleAppend(_VimTest): + snippets = ("test", """hi `!p snip.rv = "Hallo1" +snip += "Hallo2"` End""") + keys = "test" + EX + wanted = "hi Hallo1\nHallo2 End" + +class PythonCode_MultiAppend(_VimTest): + snippets = ("test", """hi `!p snip.rv = "Hallo1" +snip += "Hallo2" +snip += "Hallo3"` End""") + keys = "test" + EX + wanted = "hi Hallo1\nHallo2\nHallo3 End" + +class PythonCode_MultiAppendSimpleIndent(_VimTest): + snippets = ("test", """hi +`!p snip.rv="Hallo1" +snip += "Hallo2" +snip += "Hallo3"` +End""") + keys = """ + test""" + EX + wanted = """ + hi + Hallo1 + Hallo2 + Hallo3 + End""" + +class PythonCode_SimpleMkline(_VimTest): + snippets = ("test", r"""hi +`!p snip.rv="Hallo1\n" +snip.rv += snip.mkline("Hallo2") + "\n" +snip.rv += snip.mkline("Hallo3")` +End""") + keys = """ + test""" + EX + wanted = """ + hi + Hallo1 + Hallo2 + Hallo3 + End""" + +class PythonCode_MultiAppendShift(_VimTest): + snippets = ("test", r"""hi +`!p snip.rv="i1" +snip += "i1" +snip >> 1 +snip += "i2" +snip << 2 +snip += "i0" +snip >> 3 +snip += "i3"` +End""") + keys = """ + test""" + EX + wanted = """ + hi + i1 + i1 + i2 +i0 + i3 + End""" + +class PythonCode_MultiAppendShiftMethods(_VimTest): + snippets = ("test", r"""hi +`!p snip.rv="i1\n" +snip.rv += snip.mkline("i1\n") +snip.shift(1) +snip.rv += snip.mkline("i2\n") +snip.unshift(2) +snip.rv += snip.mkline("i0\n") +snip.shift(3) +snip.rv += snip.mkline("i3")` +End""") + keys = """ + test""" + EX + wanted = """ + hi + i1 + i1 + i2 +i0 + i3 + End""" + + +class PythonCode_ResetIndent(_VimTest): + snippets = ("test", r"""hi +`!p snip.rv="i1" +snip >> 1 +snip += "i2" +snip.reset_indent() +snip += "i1" +snip << 1 +snip += "i0" +snip.reset_indent() +snip += "i1"` +End""") + keys = """ + test""" + EX + wanted = """ + hi + i1 + i2 + i1 +i0 + i1 + End""" + +class PythonCode_IndentEtSw(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set expandtab") + snippets = ("test", r"""hi +`!p snip.rv = "i1" +snip >> 1 +snip += "i2" +snip << 2 +snip += "i0" +snip >> 1 +snip += "i1" +` +End""") + keys = """ test""" + EX + wanted = """ hi + i1 + i2 +i0 + i1 + End""" + +class PythonCode_IndentEtSwOffset(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set expandtab") + snippets = ("test", r"""hi +`!p snip.rv = "i1" +snip >> 1 +snip += "i2" +snip << 2 +snip += "i0" +snip >> 1 +snip += "i1" +` +End""") + keys = """ test""" + EX + wanted = """ hi + i1 + i2 + i0 + i1 + End""" + +class PythonCode_IndentNoetSwTs(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set ts=4") + snippets = ("test", r"""hi +`!p snip.rv = "i1" +snip >> 1 +snip += "i2" +snip << 2 +snip += "i0" +snip >> 1 +snip += "i1" +` +End""") + keys = """ test""" + EX + wanted = """ hi + i1 +\t i2 +i0 + i1 + End""" + +# Test using 'opt' +class PythonCode_OptExists(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append('let g:UStest="yes"') + snippets = ("test", r"""hi `!p snip.rv = snip.opt("g:UStest") or "no"` End""") + keys = """test""" + EX + wanted = """hi yes End""" + +class PythonCode_OptNoExists(_VimTest): + snippets = ("test", r"""hi `!p snip.rv = snip.opt("g:UStest") or "no"` End""") + keys = """test""" + EX + wanted = """hi no End""" + +class PythonCode_IndentProblem(_VimTest): + # A test case which is likely related to bug 719649 + snippets = ("test", r"""hi `!p +snip.rv = "World" +` End""") + keys = " " * 8 + "test" + EX # < 8 works. + wanted = """ hi World End""" + +class PythonCode_TrickyReferences(_VimTest): + snippets = ("test", r"""${2:${1/.+/egal/}} ${1:$3} ${3:`!p snip.rv = "hi"`}""") + keys = "ups test" + EX + wanted = "ups egal hi hi" +# locals +class PythonCode_Locals(_VimTest): + snippets = ("test", r"""hi `!p a = "test" +snip.rv = "nothing"` `!p snip.rv = a +` End""") + keys = """test""" + EX + wanted = """hi nothing test End""" + +class PythonCode_LongerTextThanSource_Chars(_VimTest): + snippets = ("test", r"""hi`!p snip.rv = "a" * 100`end""") + keys = """test""" + EX + "ups" + wanted = "hi" + 100*"a" + "endups" + +class PythonCode_LongerTextThanSource_MultiLine(_VimTest): + snippets = ("test", r"""hi`!p snip.rv = "a" * 100 + '\n'*100 + "a"*100`end""") + keys = """test""" + EX + "ups" + wanted = "hi" + 100*"a" + 100*"\n" + 100*"a" + "endups" + +class PythonCode_AccessKilledTabstop_OverwriteSecond(_VimTest): + snippets = ("test", r"`!p snip.rv = t[2].upper()`${1:h${2:welt}o}`!p snip.rv = t[2].upper()`") + keys = "test" + EX + JF + "okay" + wanted = "OKAYhokayoOKAY" +class PythonCode_AccessKilledTabstop_OverwriteFirst(_VimTest): + snippets = ("test", r"`!p snip.rv = t[2].upper()`${1:h${2:welt}o}`!p snip.rv = t[2].upper()`") + keys = "test" + EX + "aaa" + wanted = "aaa" + +class PythonVisual_NoVisualSelection_Ignore(_VimTest): + snippets = ("test", "h`!p snip.rv = snip.v.mode + snip.v.text`b") + keys = "test" + EX + "abc" + wanted = "hbabc" +class PythonVisual_SelectOneWord(_VimTest): + snippets = ("test", "h`!p snip.rv = snip.v.mode + snip.v.text`b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + wanted = "hvblablubb" +class PythonVisual_LineSelect_Simple(_VimTest): + snippets = ("test", "h`!p snip.rv = snip.v.mode + snip.v.text`b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + wanted = "hVhello\nnice\nworld\nb" + +# Tests for https://bugs.launchpad.net/bugs/1259349 +class Python_WeirdScoping_Error(_VimTest): + snippets = ("test", "h`!p import re; snip.rv = '%i' % len([re.search for i in 'aiiia'])`b") + keys = "test" + EX + wanted = "h5b" +# End: New Implementation #}}} +# End: PythonCode Interpolation #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_ListSnippets.py b/vim/vim.symlink/bundle/ultisnips/test/test_ListSnippets.py new file mode 100644 index 0000000..48975ad --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_ListSnippets.py @@ -0,0 +1,30 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# List Snippets {{{# +class _ListAllSnippets(_VimTest): + snippets = ( ("testblah", "BLAAH", "Say BLAH"), + ("test", "TEST ONE", "Say tst one"), + ("aloha", "OHEEEE", "Say OHEE"), + ) + +class ListAllAvailable_NothingTyped_ExpectCorrectResult(_ListAllSnippets): + keys = "" + LS + "3\n" + wanted = "BLAAH" +class ListAllAvailable_SpaceInFront_ExpectCorrectResult(_ListAllSnippets): + keys = " " + LS + "3\n" + wanted = " BLAAH" +class ListAllAvailable_BraceInFront_ExpectCorrectResult(_ListAllSnippets): + keys = "} " + LS + "3\n" + wanted = "} BLAAH" +class ListAllAvailable_testtyped_ExpectCorrectResult(_ListAllSnippets): + keys = "hallo test" + LS + "2\n" + wanted = "hallo BLAAH" +class ListAllAvailable_testtypedSecondOpt_ExpectCorrectResult(_ListAllSnippets): + keys = "hallo test" + LS + "1\n" + wanted = "hallo TEST ONE" + +class ListAllAvailable_NonDefined_NoExpectionShouldBeRaised(_ListAllSnippets): + keys = "hallo qualle" + LS + "Hi" + wanted = "hallo qualleHi" +# End: List Snippets #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Mirror.py b/vim/vim.symlink/bundle/ultisnips/test/test_Mirror.py new file mode 100644 index 0000000..721bdce --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Mirror.py @@ -0,0 +1,193 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Mirrors {{{# +class TextTabStopTextAfterTab_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 Hinten\n$1") + keys = "test" + EX + "hallo" + wanted = "hallo Hinten\nhallo" +class TextTabStopTextBeforeTab_ExpectCorrectResult(_VimTest): + snippets = ("test", "Vorne $1\n$1") + keys = "test" + EX + "hallo" + wanted = "Vorne hallo\nhallo" +class TextTabStopTextSurroundedTab_ExpectCorrectResult(_VimTest): + snippets = ("test", "Vorne $1 Hinten\n$1") + keys = "test" + EX + "hallo test" + wanted = "Vorne hallo test Hinten\nhallo test" + +class TextTabStopTextBeforeMirror_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\nVorne $1") + keys = "test" + EX + "hallo" + wanted = "hallo\nVorne hallo" +class TextTabStopAfterMirror_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n$1 Hinten") + keys = "test" + EX + "hallo" + wanted = "hallo\nhallo Hinten" +class TextTabStopSurroundMirror_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\nVorne $1 Hinten") + keys = "test" + EX + "hallo welt" + wanted = "hallo welt\nVorne hallo welt Hinten" +class TextTabStopAllSurrounded_ExpectCorrectResult(_VimTest): + snippets = ("test", "ObenVorne $1 ObenHinten\nVorne $1 Hinten") + keys = "test" + EX + "hallo welt" + wanted = "ObenVorne hallo welt ObenHinten\nVorne hallo welt Hinten" + +class MirrorBeforeTabstopLeave_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1:this is it} $1") + keys = "test" + EX + wanted = "this is it this is it this is it" +class MirrorBeforeTabstopOverwrite_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1:this is it} $1") + keys = "test" + EX + "a" + wanted = "a a a" + +class TextTabStopSimpleMirrorMultiline_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n$1") + keys = "test" + EX + "hallo" + wanted = "hallo\nhallo" +class SimpleMirrorMultilineMany_ExpectCorrectResult(_VimTest): + snippets = ("test", " $1\n$1\na$1b\n$1\ntest $1 mich") + keys = "test" + EX + "hallo" + wanted = " hallo\nhallo\nahallob\nhallo\ntest hallo mich" +class MultilineTabStopSimpleMirrorMultiline_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n\n$1\n\n$1") + keys = "test" + EX + "hallo Du\nHi" + wanted = "hallo Du\nHi\n\nhallo Du\nHi\n\nhallo Du\nHi" +class MultilineTabStopSimpleMirrorMultiline1_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n$1\n$1") + keys = "test" + EX + "hallo Du\nHi" + wanted = "hallo Du\nHi\nhallo Du\nHi\nhallo Du\nHi" +class MultilineTabStopSimpleMirrorDeleteInLine_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n$1\n$1") + keys = "test" + EX + "hallo Du\nHi\b\bAch Blah" + wanted = "hallo Du\nAch Blah\nhallo Du\nAch Blah\nhallo Du\nAch Blah" +class TextTabStopSimpleMirrorMultilineMirrorInFront_ECR(_VimTest): + snippets = ("test", "$1\n${1:sometext}") + keys = "test" + EX + "hallo\nagain" + wanted = "hallo\nagain\nhallo\nagain" + +class SimpleMirrorDelete_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n$1") + keys = "test" + EX + "hallo\b\b" + wanted = "hal\nhal" + +class SimpleMirrorSameLine_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 $1") + keys = "test" + EX + "hallo" + wanted = "hallo hallo" +class SimpleMirrorSameLine_InText_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 $1") + keys = "ups test blah" + ESC + "02f i" + EX + "hallo" + wanted = "ups hallo hallo blah" +class SimpleMirrorSameLineBeforeTabDefVal_ECR(_VimTest): + snippets = ("test", "$1 ${1:replace me}") + keys = "test" + EX + "hallo foo" + wanted = "hallo foo hallo foo" +class SimpleMirrorSameLineBeforeTabDefVal_DelB4Typing_ECR(_VimTest): + snippets = ("test", "$1 ${1:replace me}") + keys = "test" + EX + BS + "hallo foo" + wanted = "hallo foo hallo foo" +class SimpleMirrorSameLineMany_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 $1 $1 $1") + keys = "test" + EX + "hallo du" + wanted = "hallo du hallo du hallo du hallo du" +class SimpleMirrorSameLineManyMultiline_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 $1 $1 $1") + keys = "test" + EX + "hallo du\nwie gehts" + wanted = "hallo du\nwie gehts hallo du\nwie gehts hallo du\nwie gehts" \ + " hallo du\nwie gehts" +class SimpleMirrorDeleteSomeEnterSome_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1\n$1") + keys = "test" + EX + "hallo\b\bhups" + wanted = "halhups\nhalhups" + +class SimpleTabstopWithDefaultSimpelType_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha ${1:defa}\n$1") + keys = "test" + EX + "world" + wanted = "ha world\nworld" +class SimpleTabstopWithDefaultComplexType_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha ${1:default value} $1\nanother: $1 mirror") + keys = "test" + EX + "world" + wanted = "ha world world\nanother: world mirror" +class SimpleTabstopWithDefaultSimpelKeep_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha ${1:defa}\n$1") + keys = "test" + EX + wanted = "ha defa\ndefa" +class SimpleTabstopWithDefaultComplexKeep_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha ${1:default value} $1\nanother: $1 mirror") + keys = "test" + EX + wanted = "ha default value default value\nanother: default value mirror" + +class TabstopWithMirrorManyFromAll_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $5 ${1:blub} $4 $0 ${2:$1.h} $1 $3 ${4:More}") + keys = "test" + EX + "hi" + JF + "hu" + JF + "hub" + JF + "hulla" + \ + JF + "blah" + JF + "end" + wanted = "ha blah hi hulla end hu hi hub hulla" +class TabstopWithMirrorInDefaultNoType_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha ${1:blub} ${2:$1.h}") + keys = "test" + EX + wanted = "ha blub blub.h" +class TabstopWithMirrorInDefaultNoType1_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha ${1:blub} ${2:$1}") + keys = "test" + EX + wanted = "ha blub blub" +class TabstopWithMirrorInDefaultTwiceAndExtra_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $1 ${2:$1.h $1.c}\ntest $1") + keys = "test" + EX + "stdin" + wanted = "ha stdin stdin.h stdin.c\ntest stdin" +class TabstopWithMirrorInDefaultMultipleLeave_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $1 ${2:snip} ${3:$1.h $2}") + keys = "test" + EX + "stdin" + wanted = "ha stdin snip stdin.h snip" +class TabstopWithMirrorInDefaultMultipleOverwrite_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $1 ${2:snip} ${3:$1.h $2}") + keys = "test" + EX + "stdin" + JF + "do snap" + wanted = "ha stdin do snap stdin.h do snap" +class TabstopWithMirrorInDefaultOverwrite_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $1 ${2:$1.h}") + keys = "test" + EX + "stdin" + JF + "overwritten" + wanted = "ha stdin overwritten" +class TabstopWithMirrorInDefaultOverwrite1_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $1 ${2:$1}") + keys = "test" + EX + "stdin" + JF + "overwritten" + wanted = "ha stdin overwritten" +class TabstopWithMirrorInDefaultNoOverwrite1_ExpectCorrectResult(_VimTest): + snippets = ("test", "ha $1 ${2:$1}") + keys = "test" + EX + "stdin" + JF + JF + "end" + wanted = "ha stdin stdinend" + +class MirrorRealLifeExample_ExpectCorrectResult(_VimTest): + snippets = ( + ("for", "for(size_t ${2:i} = 0; $2 < ${1:count}; ${3:++$2})" \ + "\n{\n\t${0:/* code */}\n}"), + ) + keys ="for" + EX + "100" + JF + "avar\b\b\b\ba_variable" + JF + \ + "a_variable *= 2" + JF + "// do nothing" + wanted = """for(size_t a_variable = 0; a_variable < 100; a_variable *= 2) +{ +\t// do nothing +}""" + +class Mirror_TestKill_InsertBefore_NoKill(_VimTest): + snippets = "test", "$1 $1_" + keys = "hallo test" + EX + "auch" + ESC + "wihi" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noauch hinoauch_end" +class Mirror_TestKill_InsertAfter_NoKill(_VimTest): + snippets = "test", "$1 $1_" + keys = "hallo test" + EX + "auch" + ESC + "eiab" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noauch noauchab_end" +class Mirror_TestKill_InsertBeginning_Kill(_VimTest): + snippets = "test", "$1 $1_" + keys = "hallo test" + EX + "auch" + ESC + "wahi" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noauch ahiuch_end" +class Mirror_TestKill_InsertEnd_Kill(_VimTest): + snippets = "test", "$1 $1_" + keys = "hallo test" + EX + "auch" + ESC + "ehihi" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noauch auchih_end" +class Mirror_TestKillTabstop_Kill(_VimTest): + snippets = "test", "welt${1:welt${2:welt}welt} $2" + keys = "hallo test" + EX + "elt" + wanted = "hallo weltelt " + +# End: Mirrors #}}} + diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Movement.py b/vim/vim.symlink/bundle/ultisnips/test/test_Movement.py new file mode 100644 index 0000000..4c5ddd4 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Movement.py @@ -0,0 +1,60 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Cursor Movement {{{# +class CursorMovement_Multiline_ECR(_VimTest): + snippets = ("test", r"$1 ${1:a tab}") + keys = "test" + EX + "this is something\nvery nice\nnot" + JF + "more text" + wanted = "this is something\nvery nice\nnot " \ + "this is something\nvery nice\nnotmore text" +class CursorMovement_BS_InEditMode(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set backspace=eol,indent,start") + snippets = ("\n\t$1\n\t$2\n\n$3") + keys = "= (3,0) + +def python3(): + if PYTHON3: + return "Test does not work on python3." + +# Plugin: YouCompleteMe {{{# +# TODO(sirver): disabled because it fails right now. +# class Plugin_YouCompleteMe_IntegrationTest(_VimTest): + # def skip_if(self): + # r = python3() + # if r: + # return r + # if "7.4" not in self.version: + # return "Needs Vim 7.4." + # plugins = ["Valloric/YouCompleteMe"] + # snippets = ("superlongtrigger", "Hello") + # keys = "superlo\ty" + # wanted = "Hello" + + # def _extra_options_pre_init(self, vim_config): + # # Not sure why, but I need to make a new tab for this to work. + # vim_config.append('let g:UltiSnipsExpandTrigger="y"') + # vim_config.append('tabnew') + + # def _before_test(self): + # self.vim.send(":set ft=python\n") + # # Give ycm a chance to catch up. + # time.sleep(1) +# End: Plugin: YouCompleteMe #}}} +# Plugin: Neocomplete {{{# +class Plugin_Neocomplete_BugTest(_VimTest): + # Test for https://github.com/SirVer/ultisnips/issues/228 + def skip_if(self): + if "+lua" not in self.version: + return "Needs +lua" + plugins = ["Shougo/neocomplete.vim"] + snippets = ("t", "Hello", "", "w") + keys = "iab\\ t" + EX + wanted = "iab\\ Hello" + + def _extra_options_pre_init(self, vim_config): + vim_config.append(r'set iskeyword+=\\ ') + vim_config.append('let g:neocomplete#enable_at_startup = 1') + vim_config.append('let g:neocomplete#enable_smart_case = 1') + vim_config.append('let g:neocomplete#enable_camel_case = 1') + vim_config.append('let g:neocomplete#enable_auto_delimiter = 1') + vim_config.append('let g:neocomplete#enable_refresh_always = 1') +# End: Plugin: Neocomplete #}}} +# Plugin: unite {{{# +class Plugin_unite_BugTest(_VimTest): + plugins = ["Shougo/unite.vim"] + snippets = ("t", "Hello", "", "w") + keys = "iab\\ t=UltiSnipsCallUnite()\n" + wanted = "iab\\ Hello " + + def _extra_options_pre_init(self, vim_config): + vim_config.append(r'set iskeyword+=\\ ') + vim_config.append('function! UltiSnipsCallUnite()') + vim_config.append(' Unite -start-insert -winheight=100 -immediately -no-empty ultisnips') + vim_config.append(' return ""') + vim_config.append('endfunction') +# End: Plugin: unite #}}} +# Plugin: Supertab {{{# +class Plugin_SuperTab_SimpleTest(_VimTest): + plugins = ["ervandew/supertab"] + snippets = ("long", "Hello", "", "w") + keys = ( "longtextlongtext\n" + + "longt" + EX + "\n" + # Should complete word + "long" + EX ) # Should expand + wanted = "longtextlongtext\nlongtextlongtext\nHello" + + def _before_test(self): + # Make sure that UltiSnips has the keymap + self.vim.send(":call UltiSnips#map_keys#MapKeys()\n") + + def _extra_options_post_init(self, vim_config): + assert EX == "\t" # Otherwise this test needs changing. + vim_config.append('let g:SuperTabDefaultCompletionType = ""') + vim_config.append('let g:SuperTabRetainCompletionDuration = "insert"') + vim_config.append('let g:SuperTabLongestHighlight = 1') + vim_config.append('let g:SuperTabCrMapping = 0') +# End: Plugin: Supertab #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Recursive.py b/vim/vim.symlink/bundle/ultisnips/test/test_Recursive.py new file mode 100644 index 0000000..16b1776 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Recursive.py @@ -0,0 +1,211 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Recursive (Nested) Snippets {{{# +class RecTabStops_SimpleCase_ExpectCorrectResult(_VimTest): + snippets = ("m", "[ ${1:first} ${2:sec} ]") + keys = "m" + EX + "m" + EX + "hello" + JF + "world" + JF + "ups" + JF + "end" + wanted = "[ [ hello world ]ups end ]" +class RecTabStops_SimpleCaseLeaveSecondSecond_ExpectCorrectResult(_VimTest): + snippets = ("m", "[ ${1:first} ${2:sec} ]") + keys = "m" + EX + "m" + EX + "hello" + JF + "world" + JF + JF + JF + "end" + wanted = "[ [ hello world ] sec ]end" +class RecTabStops_SimpleCaseLeaveFirstSecond_ExpectCorrectResult(_VimTest): + snippets = ("m", "[ ${1:first} ${2:sec} ]") + keys = "m" + EX + "m" + EX + "hello" + JF + JF + JF + "world" + JF + "end" + wanted = "[ [ hello sec ] world ]end" + +class RecTabStops_InnerWOTabStop_ECR(_VimTest): + snippets = ( + ("m1", "Just some Text"), + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m1" + EX + "hi" + JF + "two" + JF + "end" + wanted = "[ Just some Texthi two ]end" +class RecTabStops_InnerWOTabStopTwiceDirectly_ECR(_VimTest): + snippets = ( + ("m1", "JST"), + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m1" + EX + " m1" + EX + "hi" + JF + "two" + JF + "end" + wanted = "[ JST JSThi two ]end" +class RecTabStops_InnerWOTabStopTwice_ECR(_VimTest): + snippets = ( + ("m1", "JST"), + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m1" + EX + JF + "m1" + EX + "hi" + JF + "end" + wanted = "[ JST JSThi ]end" +class RecTabStops_OuterOnlyWithZeroTS_ECR(_VimTest): + snippets = ( + ("m", "A $0 B"), + ("m1", "C $1 D $0 E"), + ) + keys = "m" + EX + "m1" + EX + "CD" + JF + "DE" + wanted = "A C CD D DE E B" +class RecTabStops_OuterOnlyWithZero_ECR(_VimTest): + snippets = ( + ("m", "A $0 B"), + ("m1", "C $1 D $0 E"), + ) + keys = "m" + EX + "m1" + EX + "CD" + JF + "DE" + wanted = "A C CD D DE E B" +class RecTabStops_ExpandedInZeroTS_ECR(_VimTest): + snippets = ( + ("m", "A $0 B $1"), + ("m1", "C $1 D $0 E"), + ) + keys = "m" + EX + "hi" + JF + "m1" + EX + "CD" + JF + "DE" + wanted = "A C CD D DE E B hi" +class RecTabStops_ExpandedInZeroTSTwice_ECR(_VimTest): + snippets = ( + ("m", "A $0 B $1"), + ("m1", "C $1 D $0 E"), + ) + keys = "m" + EX + "hi" + JF + "m" + EX + "again" + JF + "m1" + \ + EX + "CD" + JF + "DE" + wanted = "A A C CD D DE E B again B hi" +class RecTabStops_ExpandedInZeroTSSecondTime_ECR(_VimTest): + snippets = ( + ("m", "A $0 B $1"), + ("m1", "C $1 D $0 E"), + ) + keys = "m" + EX + "hi" + JF + "m" + EX + "m1" + EX + "CD" + JF + "DE" + JF + "AB" + wanted = "A A AB B C CD D DE E B hi" +class RecTabsStops_TypeInZero_ECR(_VimTest): + snippets = ( + ("v", r"\vec{$1}", "Vector", "w"), + ("frac", r"\frac{${1:one}}${0:zero}{${2:two}}", "Fractio", "w"), + ) + keys = "v" + EX + "frac" + EX + "a" + JF + "b" + JF + "frac" + EX + "aa" + JF + JF + "cc" + JF + \ + "hello frac" + EX + JF + JF + "world" + wanted = r"\vec{\frac{a}\frac{aa}cc{two}{b}}hello \frac{one}world{two}" +class RecTabsStops_TypeInZero2_ECR(_VimTest): + snippets = ( + ("m", r"_${0:explicit zero}", "snip", "i"), + ) + keys = "m" + EX + "hello m" + EX + "world m" + EX + "end" + wanted = r"_hello _world _end" +class RecTabsStops_BackspaceZero_ECR(_VimTest): + snippets = ( + ("m", r"${1:one}${0:explicit zero}${2:two}", "snip", "i"), + ) + keys = "m" + EX + JF + JF + BS + "m" + EX + wanted = r"oneoneexplicit zerotwotwo" + + +class RecTabStops_MirrorInnerSnippet_ECR(_VimTest): + snippets = ( + ("m", "[ $1 $2 ] $1"), + ("m1", "ASnip $1 ASnip $2 ASnip"), + ) + keys = "m" + EX + "m1" + EX + "Hallo" + JF + "Hi" + JF + "endone" + JF + "two" + JF + "totalend" + wanted = "[ ASnip Hallo ASnip Hi ASnipendone two ] ASnip Hallo ASnip Hi ASnipendonetotalend" + +class RecTabStops_NotAtBeginningOfTS_ExpectCorrectResult(_VimTest): + snippets = ("m", "[ ${1:first} ${2:sec} ]") + keys = "m" + EX + "hello m" + EX + "hi" + JF + "two" + JF + "ups" + JF + "three" + \ + JF + "end" + wanted = "[ hello [ hi two ]ups three ]end" +class RecTabStops_InNewlineInTabstop_ExpectCorrectResult(_VimTest): + snippets = ("m", "[ ${1:first} ${2:sec} ]") + keys = "m" + EX + "hello\nm" + EX + "hi" + JF + "two" + JF + "ups" + JF + "three" + \ + JF + "end" + wanted = "[ hello\n[ hi two ]ups three ]end" +class RecTabStops_InNewlineInTabstopNotAtBeginOfLine_ECR(_VimTest): + snippets = ("m", "[ ${1:first} ${2:sec} ]") + keys = "m" + EX + "hello\nhello again m" + EX + "hi" + JF + "two" + \ + JF + "ups" + JF + "three" + JF + "end" + wanted = "[ hello\nhello again [ hi two ]ups three ]end" + +class RecTabStops_InNewlineMultiline_ECR(_VimTest): + snippets = ("m", "M START\n$0\nM END") + keys = "m" + EX + "m" + EX + wanted = "M START\nM START\n\nM END\nM END" +class RecTabStops_InNewlineManualIndent_ECR(_VimTest): + snippets = ("m", "M START\n$0\nM END") + keys = "m" + EX + " m" + EX + "hi" + wanted = "M START\n M START\n hi\n M END\nM END" +class RecTabStops_InNewlineManualIndentTextInFront_ECR(_VimTest): + snippets = ("m", "M START\n$0\nM END") + keys = "m" + EX + " hallo m" + EX + "hi" + wanted = "M START\n hallo M START\n hi\n M END\nM END" +class RecTabStops_InNewlineMultilineWithIndent_ECR(_VimTest): + snippets = ("m", "M START\n $0\nM END") + keys = "m" + EX + "m" + EX + "hi" + wanted = "M START\n M START\n hi\n M END\nM END" +class RecTabStops_InNewlineMultilineWithNonZeroTS_ECR(_VimTest): + snippets = ("m", "M START\n $1\nM END -> $0") + keys = "m" + EX + "m" + EX + "hi" + JF + "hallo" + JF + "end" + wanted = "M START\n M START\n hi\n M END -> hallo\n" \ + "M END -> end" + +class RecTabStops_BarelyNotLeavingInner_ECR(_VimTest): + snippets = ( + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m" + EX + "a" + 3*ARR_L + JF + "hallo" + \ + JF + "ups" + JF + "world" + JF + "end" + wanted = "[ [ a hallo ]ups world ]end" +class RecTabStops_LeavingInner_ECR(_VimTest): + snippets = ( + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m" + EX + "a" + 4*ARR_L + JF + "hallo" + \ + JF + "world" + wanted = "[ [ a sec ] hallo ]world" +class RecTabStops_LeavingInnerInner_ECR(_VimTest): + snippets = ( + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m" + EX + "m" + EX + "a" + 4*ARR_L + JF + "hallo" + \ + JF + "ups" + JF + "world" + JF + "end" + wanted = "[ [ [ a sec ] hallo ]ups world ]end" +class RecTabStops_LeavingInnerInnerTwo_ECR(_VimTest): + snippets = ( + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m" + EX + "m" + EX + "a" + 6*ARR_L + JF + "hallo" + \ + JF + "end" + wanted = "[ [ [ a sec ] sec ] hallo ]end" + + +class RecTabStops_ZeroTSisNothingSpecial_ECR(_VimTest): + snippets = ( + ("m1", "[ ${1:first} $0 ${2:sec} ]"), + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m1" + EX + "one" + JF + "two" + \ + JF + "three" + JF + "four" + JF + "end" + wanted = "[ [ one three two ] four ]end" +class RecTabStops_MirroredZeroTS_ECR(_VimTest): + snippets = ( + ("m1", "[ ${1:first} ${0:Year, some default text} $0 ${2:sec} ]"), + ("m", "[ ${1:first} ${2:sec} ]"), + ) + keys = "m" + EX + "m1" + EX + "one" + JF + "two" + \ + JF + "three" + JF + "four" + JF + "end" + wanted = "[ [ one three three two ] four ]end" +class RecTabStops_ChildTriggerContainsParentTextObjects(_VimTest): + # https://bugs.launchpad.net/bugs/1191617 + files = { "us/all.snippets": r""" +global !p +def complete(t, opts): + if t: + opts = [ q[len(t):] for q in opts if q.startswith(t) ] + if len(opts) == 0: + return '' + return opts[0] if len(opts) == 1 else "(" + '|'.join(opts) + ')' +def autocomplete_options(t, string, attr=None): + return complete(t[1], [opt for opt in attr if opt not in string]) +endglobal +snippet /form_for(.*){([^|]*)/ "form_for html options" rw! +`!p +auto = autocomplete_options(t, match.group(2), attr=["id: ", "class: ", "title: "]) +snip.rv = "form_for" + match.group(1) + "{"`$1`!p if (snip.c != auto) : snip.rv=auto` +endsnippet +"""} + keys = "form_for user, namespace: some_namespace, html: {i" + EX + "i" + EX + wanted = "form_for user, namespace: some_namespace, html: {(id: |class: |title: )d: " +# End: Recursive (Nested) Snippets #}}} + diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Selection.py b/vim/vim.symlink/bundle/ultisnips/test/test_Selection.py new file mode 100644 index 0000000..7a00183 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Selection.py @@ -0,0 +1,93 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Unmap SelectMode Mappings {{{# +# Test for bug 427298 # +class _SelectModeMappings(_VimTest): + snippets = ("test", "${1:World}") + keys = "test" + EX + "Hello" + wanted = "Hello" + maps = ("", "") + buffer_maps = ("", "") + do_unmapping = True + ignores = [] + + def _extra_options_pre_init(self, vim_config): + vim_config.append(":let g:UltiSnipsRemoveSelectModeMappings=%i" % int(self.do_unmapping)) + vim_config.append(":let g:UltiSnipsMappingsToIgnore=%s" % repr(self.ignores)) + + if not isinstance(self.maps[0], tuple): + self.maps = (self.maps,) + if not isinstance(self.buffer_maps[0], tuple): + self.buffer_maps = (self.buffer_maps,) + + for key, m in self.maps: + if not len(key): continue + vim_config.append(":smap %s %s" % (key,m)) + for key, m in self.buffer_maps: + if not len(key): continue + vim_config.append(":smap %s %s" % (key,m)) + +class SelectModeMappings_RemoveBeforeSelecting_ECR(_SelectModeMappings): + maps = ("H", "x") + wanted = "Hello" +class SelectModeMappings_DisableRemoveBeforeSelecting_ECR(_SelectModeMappings): + do_unmapping = False + maps = ("H", "x") + wanted = "xello" +class SelectModeMappings_IgnoreMappings_ECR(_SelectModeMappings): + ignores = ["e"] + maps = ("H", "x"), ("e", "l") + wanted = "Hello" +class SelectModeMappings_IgnoreMappings1_ECR(_SelectModeMappings): + ignores = ["H"] + maps = ("H", "x"), ("e", "l") + wanted = "xello" +class SelectModeMappings_IgnoreMappings2_ECR(_SelectModeMappings): + ignores = ["e", "H"] + maps = ("e", "l"), ("H", "x") + wanted = "xello" +class SelectModeMappings_BufferLocalMappings_ECR(_SelectModeMappings): + buffer_maps = ("H", "blah") + wanted = "Hello" +# End: Unmap SelectMode Mappings #}}} + +# Exclusive Selection {{{# +class _ES_Base(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set selection=exclusive") +class ExclusiveSelection_SimpleTabstop_Test(_ES_Base): + snippets = ("test", "h${1:blah}w $1") + keys = "test" + EX + "ui" + JF + wanted = "huiw ui" + +class ExclusiveSelection_RealWorldCase_Test(_ES_Base): + snippets = ("for", +"""for ($${1:i} = ${2:0}; $$1 < ${3:count}; $$1${4:++}) { + ${5:// code} +}""") + keys = "for" + EX + "k" + JF + wanted = """for ($k = 0; $k < count; $k++) { + // code +}""" +# End: Exclusive Selection #}}} + +# Old Selection {{{# +class _OS_Base(_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set selection=old") +class OldSelection_SimpleTabstop_Test(_OS_Base): + snippets =("test", "h${1:blah}w $1") + keys = "test" + EX + "ui" + JF + wanted = "huiw ui" + +class OldSelection_RealWorldCase_Test(_OS_Base): + snippets = ("for", +"""for ($${1:i} = ${2:0}; $$1 < ${3:count}; $$1${4:++}) { + ${5:// code} +}""") + keys = "for" + EX + "k" + JF + wanted = """for ($k = 0; $k < count; $k++) { + // code +}""" +# End: Old Selection #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_SnipMate.py b/vim/vim.symlink/bundle/ultisnips/test/test_SnipMate.py new file mode 100644 index 0000000..b17820e --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_SnipMate.py @@ -0,0 +1,120 @@ +# encoding: utf-8 +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# snipMate support {{{# +class snipMate_SimpleSnippet(_VimTest): + files = { "snippets/_.snippets": """ +snippet hello +\tThis is a test snippet +\t# With a comment"""} + keys = "hello" + EX + wanted = "This is a test snippet\n# With a comment" +class snipMate_OtherFiletype(_VimTest): + files = { "snippets/blubi.snippets": """ +snippet hello +\tworked"""} + keys = "hello" + EX + ESC + ":set ft=blubi\nohello" + EX + wanted = "hello" + EX + "\nworked" +class snipMate_MultiMatches(_VimTest): + files = { "snippets/_.snippets": """ +snippet hello The first snippet." +\tone +snippet hello The second snippet. +\ttwo"""} + keys = "hello" + EX + "2\n" + wanted = "two" +class snipMate_SimpleSnippetSubDirectory(_VimTest): + files = { "snippets/_/blub.snippets": """ +snippet hello +\tThis is a test snippet"""} + keys = "hello" + EX + wanted = "This is a test snippet" +class snipMate_SimpleSnippetInSnippetFile(_VimTest): + files = { + "snippets/_/hello.snippet": """This is a stand alone snippet""", + "snippets/_/hello1.snippet": """This is two stand alone snippet""", + "snippets/_/hello2/this_is_my_cool_snippet.snippet": """Three""", + } + keys = "hello" + EX + "\nhello1" + EX + "\nhello2" + EX + wanted = "This is a stand alone snippet\nThis is two stand alone snippet\nThree" +class snipMate_Interpolation(_VimTest): + files = { "snippets/_.snippets": """ +snippet test +\tla`printf('c%02d', 3)`lu"""} + keys = "test" + EX + wanted = "lac03lu" +class snipMate_InterpolationWithSystem(_VimTest): + files = { "snippets/_.snippets": """ +snippet test +\tla`system('echo -ne öäü')`lu"""} + keys = "test" + EX + wanted = "laöäülu" +class snipMate_TestMirrors(_VimTest): + files = { "snippets/_.snippets": """ +snippet for +\tfor (${2:i}; $2 < ${1:count}; $1++) { +\t\t${4} +\t}"""} + keys = "for" + EX + "blub" + JF + "j" + JF + "hi" + wanted = "for (j; j < blub; blub++) {\n\thi\n}" +class snipMate_TestMirrorsInPlaceholders(_VimTest): + files = { "snippets/_.snippets": """ +snippet opt +\t"""} + keys = "opt" + EX + "some" + JF + JF + "ende" + wanted = """ende""" +class snipMate_TestMirrorsInPlaceholders_Overwrite(_VimTest): + files = { "snippets/_.snippets": """ +snippet opt +\t"""} + keys = "opt" + EX + "some" + JF + "not" + JF + "ende" + wanted = """ende""" +class snipMate_Visual_Simple(_VimTest): + files = { "snippets/_.snippets": """ +snippet v +\th${VISUAL}b"""} + keys = "blablub" + ESC + "0v6l" + EX + "v" + EX + wanted = "hblablubb" +class snipMate_NoNestedTabstops(_VimTest): + files = { "snippets/_.snippets": """ +snippet test +\th$${1:${2:blub}}$$"""} + keys = "test" + EX + JF + "hi" + wanted = "h$${2:blub}$$hi" +class snipMate_Extends(_VimTest): + files = { "snippets/a.snippets": """ +extends b +snippet test +\tblub""", "snippets/b.snippets": """ +snippet test1 +\tblah""" +} + keys = ESC + ":set ft=a\n" + "itest1" + EX + wanted = "blah" +class snipMate_EmptyLinesContinueSnippets(_VimTest): + files = { "snippets/_.snippets": """ +snippet test +\tblub + +\tblah + +snippet test1 +\ta""" +} + keys = "test" + EX + wanted = "blub\n\nblah\n" +class snipMate_OverwrittenByRegExpTrigger(_VimTest): + files = { "snippets/_.snippets": """ +snippet def +\tsnipmate +""", + "us/all.snippets": r""" +snippet "(de)?f" "blub" r +ultisnips +endsnippet +""" } + keys = "def" + EX + wanted = "ultisnips" +# End: snipMate support #}}} + diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_SnippetOptions.py b/vim/vim.symlink/bundle/ultisnips/test/test_SnippetOptions.py new file mode 100644 index 0000000..28d43d9 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_SnippetOptions.py @@ -0,0 +1,255 @@ +# encoding: utf-8 +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * +from test.util import running_on_windows + +# Snippet Options {{{# +class SnippetOptions_OnlyExpandWhenWSInFront_Expand(_VimTest): + snippets = ("test", "Expand me!", "", "b") + keys = "test" + EX + wanted = "Expand me!" +class SnippetOptions_OnlyExpandWhenWSInFront_Expand2(_VimTest): + snippets = ("test", "Expand me!", "", "b") + keys = " test" + EX + wanted = " Expand me!" +class SnippetOptions_OnlyExpandWhenWSInFront_DontExpand(_VimTest): + snippets = ("test", "Expand me!", "", "b") + keys = "a test" + EX + wanted = "a test" + EX +class SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWO(_VimTest): + snippets = ( + ("test", "Expand me!", "", "b"), + ("test", "not at beginning", "", ""), + ) + keys = "a test" + EX + wanted = "a not at beginning" +class SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWOChoose(_VimTest): + snippets = ( + ("test", "Expand me!", "", "b"), + ("test", "not at beginning", "", ""), + ) + keys = " test" + EX + "1\n" + wanted = " Expand me!" + + +class SnippetOptions_ExpandInwordSnippets_SimpleExpand(_VimTest): + snippets = (("test", "Expand me!", "", "i"), ) + keys = "atest" + EX + wanted = "aExpand me!" +class SnippetOptions_ExpandInwordSnippets_ExpandSingle(_VimTest): + snippets = (("test", "Expand me!", "", "i"), ) + keys = "test" + EX + wanted = "Expand me!" +class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand(_VimTest): + snippets = (("test", "Expand me!", "", "i"), ) + keys = "$test" + EX + wanted = "$Expand me!" +class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand2(_VimTest): + snippets = (("test", "Expand me!", "", "i"), ) + keys = "-test" + EX + wanted = "-Expand me!" +class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand3(_VimTest): + skip_if = lambda self: running_on_windows() + snippets = (("test", "Expand me!", "", "i"), ) + keys = "ßßtest" + EX + wanted = "ßßExpand me!" + +class _SnippetOptions_ExpandWordSnippets(_VimTest): + snippets = (("test", "Expand me!", "", "w"), ) +class SnippetOptions_ExpandWordSnippets_NormalExpand( + _SnippetOptions_ExpandWordSnippets): + keys = "test" + EX + wanted = "Expand me!" +class SnippetOptions_ExpandWordSnippets_NoExpand( + _SnippetOptions_ExpandWordSnippets): + keys = "atest" + EX + wanted = "atest" + EX +class SnippetOptions_ExpandWordSnippets_ExpandSuffix( + _SnippetOptions_ExpandWordSnippets): + keys = "a-test" + EX + wanted = "a-Expand me!" +class SnippetOptions_ExpandWordSnippets_ExpandSuffix2( + _SnippetOptions_ExpandWordSnippets): + keys = "a(test" + EX + wanted = "a(Expand me!" +class SnippetOptions_ExpandWordSnippets_ExpandSuffix3( + _SnippetOptions_ExpandWordSnippets): + keys = "[[test" + EX + wanted = "[[Expand me!" + +class _No_Tab_Expand(_VimTest): + snippets = ("test", "\t\tExpand\tme!\t", "", "t") +class No_Tab_Expand_Simple(_No_Tab_Expand): + keys = "test" + EX + wanted = "\t\tExpand\tme!\t" +class No_Tab_Expand_Leading_Spaces(_No_Tab_Expand): + keys = " test" + EX + wanted = " \t\tExpand\tme!\t" +class No_Tab_Expand_Leading_Tabs(_No_Tab_Expand): + keys = "\ttest" + EX + wanted = "\t\t\tExpand\tme!\t" +class No_Tab_Expand_No_TS(_No_Tab_Expand): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set sts=3") + keys = "test" + EX + wanted = "\t\tExpand\tme!\t" +class No_Tab_Expand_ET(_No_Tab_Expand): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set expandtab") + keys = "test" + EX + wanted = "\t\tExpand\tme!\t" +class No_Tab_Expand_ET_Leading_Spaces(_No_Tab_Expand): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set expandtab") + keys = " test" + EX + wanted = " \t\tExpand\tme!\t" +class No_Tab_Expand_ET_SW(_No_Tab_Expand): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=8") + vim_config.append("set expandtab") + keys = "test" + EX + wanted = "\t\tExpand\tme!\t" +class No_Tab_Expand_ET_SW_TS(_No_Tab_Expand): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set sw=3") + vim_config.append("set sts=3") + vim_config.append("set ts=3") + vim_config.append("set expandtab") + keys = "test" + EX + wanted = "\t\tExpand\tme!\t" + +class _TabExpand_RealWorld(object): + snippets = ("hi", +r"""hi +`!p snip.rv="i1\n" +snip.rv += snip.mkline("i1\n") +snip.shift(1) +snip.rv += snip.mkline("i2\n") +snip.unshift(2) +snip.rv += snip.mkline("i0\n") +snip.shift(3) +snip.rv += snip.mkline("i3")` +snip.rv = repr(snip.rv) +End""") + +class No_Tab_Expand_RealWorld(_TabExpand_RealWorld,_VimTest): + def _extra_options_pre_init(self, vim_config): + vim_config.append("set noexpandtab") + keys = "\t\thi" + EX + wanted = """\t\thi +\t\ti1 +\t\ti1 +\t\t\ti2 +\ti0 +\t\t\t\ti3 +\t\tsnip.rv = repr(snip.rv) +\t\tEnd""" + + +class SnippetOptions_Regex_Expand(_VimTest): + snippets = ("(test)", "Expand me!", "", "r") + keys = "test" + EX + wanted = "Expand me!" +class SnippetOptions_Regex_Multiple(_VimTest): + snippets = ("(test *)+", "Expand me!", "", "r") + keys = "test test test" + EX + wanted = "Expand me!" + +class _Regex_Self(_VimTest): + snippets = ("((?<=\W)|^)(\.)", "self.", "", "r") +class SnippetOptions_Regex_Self_Start(_Regex_Self): + keys = "." + EX + wanted = "self." +class SnippetOptions_Regex_Self_Space(_Regex_Self): + keys = " ." + EX + wanted = " self." +class SnippetOptions_Regex_Self_TextAfter(_Regex_Self): + keys = " .a" + EX + wanted = " .a" + EX +class SnippetOptions_Regex_Self_TextBefore(_Regex_Self): + keys = "a." + EX + wanted = "a." + EX +class SnippetOptions_Regex_PythonBlockMatch(_VimTest): + snippets = (r"([abc]+)([def]+)", r"""`!p m = match +snip.rv += m.group(2) +snip.rv += m.group(1) +`""", "", "r") + keys = "test cabfed" + EX + wanted = "test fedcab" +class SnippetOptions_Regex_PythonBlockNoMatch(_VimTest): + snippets = (r"cabfed", r"""`!p snip.rv = match or "No match"`""") + keys = "test cabfed" + EX + wanted = "test No match" +# Tests for Bug #691575 +class SnippetOptions_Regex_SameLine_Long_End(_VimTest): + snippets = ("(test.*)", "Expand me!", "", "r") + keys = "test test abc" + EX + wanted = "Expand me!" +class SnippetOptions_Regex_SameLine_Long_Start(_VimTest): + snippets = ("(.*test)", "Expand me!", "", "r") + keys = "abc test test" + EX + wanted = "Expand me!" +class SnippetOptions_Regex_SameLine_Simple(_VimTest): + snippets = ("(test)", "Expand me!", "", "r") + keys = "abc test test" + EX + wanted = "abc test Expand me!" + + +class MultiWordSnippet_Simple(_VimTest): + snippets = ("test me", "Expand me!") + keys = "test me" + EX + wanted = "Expand me!" +class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_Expand(_VimTest): + snippets = ("test it", "Expand me!", "", "b") + keys = "test it" + EX + wanted = "Expand me!" +class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_Expand2(_VimTest): + snippets = ("test it", "Expand me!", "", "b") + keys = " test it" + EX + wanted = " Expand me!" +class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_DontExpand(_VimTest): + snippets = ("test it", "Expand me!", "", "b") + keys = "a test it" + EX + wanted = "a test it" + EX +class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWO(_VimTest): + snippets = ( + ("test it", "Expand me!", "", "b"), + ("test it", "not at beginning", "", ""), + ) + keys = "a test it" + EX + wanted = "a not at beginning" +class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWOChoose(_VimTest): + snippets = ( + ("test it", "Expand me!", "", "b"), + ("test it", "not at beginning", "", ""), + ) + keys = " test it" + EX + "1\n" + wanted = " Expand me!" + +class MultiWord_SnippetOptions_ExpandInwordSnippets_SimpleExpand(_VimTest): + snippets = (("test it", "Expand me!", "", "i"), ) + keys = "atest it" + EX + wanted = "aExpand me!" +class MultiWord_SnippetOptions_ExpandInwordSnippets_ExpandSingle(_VimTest): + snippets = (("test it", "Expand me!", "", "i"), ) + keys = "test it" + EX + wanted = "Expand me!" + +class _MultiWord_SnippetOptions_ExpandWordSnippets(_VimTest): + snippets = (("test it", "Expand me!", "", "w"), ) +class MultiWord_SnippetOptions_ExpandWordSnippets_NormalExpand( + _MultiWord_SnippetOptions_ExpandWordSnippets): + keys = "test it" + EX + wanted = "Expand me!" +class MultiWord_SnippetOptions_ExpandWordSnippets_NoExpand( + _MultiWord_SnippetOptions_ExpandWordSnippets): + keys = "atest it" + EX + wanted = "atest it" + EX +class MultiWord_SnippetOptions_ExpandWordSnippets_ExpandSuffix( + _MultiWord_SnippetOptions_ExpandWordSnippets): + keys = "a-test it" + EX + wanted = "a-Expand me!" +# Snippet Options #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_SnippetPriorities.py b/vim/vim.symlink/bundle/ultisnips/test/test_SnippetPriorities.py new file mode 100644 index 0000000..a43a3ea --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_SnippetPriorities.py @@ -0,0 +1,145 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# Snippet Priority {{{# +class SnippetPriorities_MultiWordTriggerOverwriteExisting(_VimTest): + snippets = ( + ("test me", "${1:Hallo}", "Types Hallo"), + ("test me", "${1:World}", "Types World"), + ("test me", "We overwrite", "Overwrite the two", "", 1), + ) + keys = "test me" + EX + wanted = "We overwrite" + +class SnippetPriorities_DoNotCareAboutNonMatchings(_VimTest): + snippets = ( + ("test1", "Hallo", "Types Hallo"), + ("test2", "We overwrite", "Overwrite the two", "", 1), + ) + keys = "test1" + EX + wanted = "Hallo" + +class SnippetPriorities_OverwriteExisting(_VimTest): + snippets = ( + ("test", "${1:Hallo}", "Types Hallo"), + ("test", "${1:World}", "Types World"), + ("test", "We overwrite", "Overwrite the two", "", 1), + ) + keys = "test" + EX + wanted = "We overwrite" + +class SnippetPriorities_OverwriteTwice_ECR(_VimTest): + snippets = ( + ("test", "${1:Hallo}", "Types Hallo"), + ("test", "${1:World}", "Types World"), + ("test", "We overwrite", "Overwrite the two", "", 1), + ("test", "again", "Overwrite again", "", 2), + ) + keys = "test" + EX + wanted = "again" + +class SnippetPriorities_OverwriteThenChoose_ECR(_VimTest): + snippets = ( + ("test", "${1:Hallo}", "Types Hallo"), + ("test", "${1:World}", "Types World"), + ("test", "We overwrite", "Overwrite the two", "", 1), + ("test", "No overwrite", "Not overwritten", "", 1), + ) + keys = "test" + EX + "1\n\n" + "test" + EX + "2\n" + wanted = "We overwrite\nNo overwrite" + +class SnippetPriorities_AddedHasHigherThanFile(_VimTest): + files = { "us/all.snippets": r""" + snippet test "Test Snippet" b + This is a test snippet + endsnippet + """} + snippets = ( + ("test", "We overwrite", "Overwrite the two", "", 1), + ) + keys = "test" + EX + wanted = "We overwrite" + +class SnippetPriorities_FileHasHigherThanAdded(_VimTest): + files = { "us/all.snippets": r""" + snippet test "Test Snippet" b + This is a test snippet + endsnippet + """} + snippets = ( + ("test", "We do not overwrite", "Overwrite the two", "", -1), + ) + keys = "test" + EX + wanted = "This is a test snippet" + +class SnippetPriorities_FileHasHigherThanAdded(_VimTest): + files = { "us/all.snippets": r""" + priority -3 + snippet test "Test Snippet" b + This is a test snippet + endsnippet + """} + snippets = ( + ("test", "We overwrite", "Overwrite the two", "", -5), + ) + keys = "test" + EX + wanted = "This is a test snippet" + +class SnippetPriorities_SimpleClear(_VimTest): + files = { + "us/all.snippets": r""" + priority 1 + clearsnippets + priority -1 + snippet test "Test Snippet" + Should not expand to this. + endsnippet + """ + } + keys = "test" + EX + wanted = "test" + EX + +class SnippetPriorities_SimpleClear2(_VimTest): + files = { + "us/all.snippets": r""" + clearsnippets + snippet test "Test snippet" + Should not expand to this. + endsnippet + """ + } + keys = "test" + EX + wanted = "test" + EX + +class SnippetPriorities_ClearedByParent(_VimTest): + files = { + "us/p.snippets": r""" + clearsnippets + """, + "us/c.snippets": r""" + extends p + snippet test "Test snippets" + Should not expand to this. + endsnippet + """ + } + keys = ESC + ":set ft=c\n" + "itest" + EX + wanted = "test" + EX + +class SnippetPriorities_ClearedByChild(_VimTest): + files = { + "us/p.snippets": r""" + snippet test "Test snippets" + Should only expand in p. + endsnippet + """, + "us/c.snippets": r""" + extends p + clearsnippets + """ + } + keys = (ESC + ":set ft=p\n" + "itest" + EX + "\n" + + ESC + ":set ft=c\n" + "itest" + EX + ESC + ":set ft=p") + wanted = "Should only expand in p.\ntest" + EX + +# End: Snippet Priority #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_TabStop.py b/vim/vim.symlink/bundle/ultisnips/test/test_TabStop.py new file mode 100644 index 0000000..73f105b --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_TabStop.py @@ -0,0 +1,258 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +class TabStopSimpleReplace_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo ${0:End} ${1:Beginning}") + keys = "hallo" + EX + "na" + JF + "Du Nase" + wanted = "hallo Du Nase na" +class TabStopSimpleReplaceZeroLengthTabstops_ExpectCorrectResult(_VimTest): + snippets = ("test", r":latex:\`$1\`$0") + keys = "test" + EX + "Hello" + JF + "World" + wanted = ":latex:`Hello`World" +class TabStopSimpleReplaceReversed_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo ${1:End} ${0:Beginning}") + keys = "hallo" + EX + "na" + JF + "Du Nase" + wanted = "hallo na Du Nase" +class TabStopSimpleReplaceSurrounded_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo ${0:End} a small feed") + keys = "hallo" + EX + "Nase" + wanted = "hallo Nase a small feed" +class TabStopSimpleReplaceSurrounded1_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo $0 a small feed") + keys = "hallo" + EX + "Nase" + wanted = "hallo Nase a small feed" +class TabStop_Exit_ExpectCorrectResult(_VimTest): + snippets = ("echo", "$0 run") + keys = "echo" + EX + "test" + wanted = "test run" + +class TabStopNoReplace_ExpectCorrectResult(_VimTest): + snippets = ("echo", "echo ${1:Hallo}") + keys = "echo" + EX + wanted = "echo Hallo" + +class TabStop_EscapingCharsBackticks(_VimTest): + snippets = ("test", r"snip \` literal") + keys = "test" + EX + wanted = "snip ` literal" +class TabStop_EscapingCharsDollars(_VimTest): + snippets = ("test", r"snip \$0 $$0 end") + keys = "test" + EX + "hi" + wanted = "snip $0 $hi end" +class TabStop_EscapingCharsDollars1(_VimTest): + snippets = ("test", r"a\${1:literal}") + keys = "test" + EX + wanted = "a${1:literal}" +class TabStop_EscapingCharsDollars_BeginningOfLine(_VimTest): + snippets = ("test", "\n\\${1:literal}") + keys = "test" + EX + wanted = "\n${1:literal}" +class TabStop_EscapingCharsDollars_BeginningOfDefinitionText(_VimTest): + snippets = ("test", "\\${1:literal}") + keys = "test" + EX + wanted = "${1:literal}" +class TabStop_EscapingChars_Backslash(_VimTest): + snippets = ("test", r"This \ is a backslash!") + keys = "test" + EX + wanted = "This \\ is a backslash!" +class TabStop_EscapingChars_Backslash2(_VimTest): + snippets = ("test", r"This is a backslash \\ done") + keys = "test" + EX + wanted = r"This is a backslash \ done" +class TabStop_EscapingChars_Backslash3(_VimTest): + snippets = ("test", r"These are two backslashes \\\\ done") + keys = "test" + EX + wanted = r"These are two backslashes \\ done" +class TabStop_EscapingChars_Backslash4(_VimTest): + # Test for bug 746446 + snippets = ("test", r"\\$1{$2}") + keys = "test" + EX + "hello" + JF + "world" + wanted = r"\hello{world}" +class TabStop_EscapingChars_RealLife(_VimTest): + snippets = ("test", r"usage: \`basename \$0\` ${1:args}") + keys = "test" + EX + "[ -u -v -d ]" + wanted = "usage: `basename $0` [ -u -v -d ]" + +class TabStopEscapingWhenSelected_ECR(_VimTest): + snippets = ("test", "snip ${1:default}") + keys = "test" + EX + ESC + "0ihi" + wanted = "hisnip default" +class TabStopEscapingWhenSelectedSingleCharTS_ECR(_VimTest): + snippets = ("test", "snip ${1:i}") + keys = "test" + EX + ESC + "0ihi" + wanted = "hisnip i" +class TabStopEscapingWhenSelectedNoCharTS_ECR(_VimTest): + snippets = ("test", "snip $1") + keys = "test" + EX + ESC + "0ihi" + wanted = "hisnip " + +class TabStopWithOneChar_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "nothing ${1:i} hups") + keys = "hallo" + EX + "ship" + wanted = "nothing ship hups" + +class TabStopTestJumping_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo ${2:End} mitte ${1:Beginning}") + keys = "hallo" + EX + JF + "Test" + JF + "Hi" + wanted = "hallo Test mitte BeginningHi" +class TabStopTestJumping2_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo $2 $1") + keys = "hallo" + EX + JF + "Test" + JF + "Hi" + wanted = "hallo Test Hi" +class TabStopTestJumpingRLExampleWithZeroTab_ExpectCorrectResult(_VimTest): + snippets = ("test", "each_byte { |${1:byte}| $0 }") + keys = "test" + EX + JF + "Blah" + wanted = "each_byte { |byte| Blah }" + +class TabStopTestJumpingDontJumpToEndIfThereIsTabZero_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo $0 $1") + keys = "hallo" + EX + "Test" + JF + "Hi" + JF + JF + "du" + wanted = "hallo Hi" + 2*JF + "du Test" + +class TabStopTestBackwardJumping_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo ${2:End} mitte${1:Beginning}") + keys = "hallo" + EX + "Somelengthy Text" + JF + "Hi" + JB + \ + "Lets replace it again" + JF + "Blah" + JF + JB*2 + JF + wanted = "hallo Blah mitteLets replace it again" + JB*2 + JF +class TabStopTestBackwardJumping2_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo $2 $1") + keys = "hallo" + EX + "Somelengthy Text" + JF + "Hi" + JB + \ + "Lets replace it again" + JF + "Blah" + JF + JB*2 + JF + wanted = "hallo Blah Lets replace it again" + JB*2 + JF + +class TabStopTestMultilineExpand_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "hallo $0\nnice $1 work\n$3 $2\nSeem to work") + keys ="test hallo World" + ESC + "02f i" + EX + "world" + JF + "try" + \ + JF + "test" + JF + "one more" + JF + wanted = "test hallo one more" + JF + "\nnice world work\n" \ + "test try\nSeem to work World" + +class TabStop_TSInDefaultTextRLExample_OverwriteNone_ECR(_VimTest): + snippets = ("test", """\n $0\n""") + keys = "test" + EX + wanted = """
\n \n
""" +class TabStop_TSInDefaultTextRLExample_OverwriteFirst_NoJumpBack(_VimTest): + snippets = ("test", """\n $0\n""") + keys = "test" + EX + " blah" + JF + "Hallo" + wanted = """
\n Hallo\n
""" +class TabStop_TSInDefaultTextRLExample_DeleteFirst(_VimTest): + snippets = ("test", """\n $0\n""") + keys = "test" + EX + BS + JF + "Hallo" + wanted = """
\n Hallo\n
""" +class TabStop_TSInDefaultTextRLExample_OverwriteFirstJumpBack(_VimTest): + snippets = ("test", """\n $3 $0\n""") + keys = "test" + EX + "Hi" + JF + "Hallo" + JB + "SomethingElse" + JF + \ + "Nupl" + JF + "Nox" + wanted = """\n Nupl Nox\n""" +class TabStop_TSInDefaultTextRLExample_OverwriteSecond(_VimTest): + snippets = ("test", """\n $0\n""") + keys = "test" + EX + JF + "no" + JF + "End" + wanted = """
\n End\n
""" +class TabStop_TSInDefaultTextRLExample_OverwriteSecondTabBack(_VimTest): + snippets = ("test", """\n $3 $0\n""") + keys = "test" + EX + JF + "no" + JF + "End" + JB + "yes" + JF + "Begin" \ + + JF + "Hi" + wanted = """
\n Begin Hi\n
""" +class TabStop_TSInDefaultTextRLExample_OverwriteSecondTabBackTwice(_VimTest): + snippets = ("test", """\n $3 $0\n""") + keys = "test" + EX + JF + "no" + JF + "End" + JB + "yes" + JB + \ + " allaway" + JF + "Third" + JF + "Last" + wanted = """
\n Third Last\n
""" + +class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecond(_VimTest): + snippets = ("test", """h${1:a$2b}l""") + keys = "test" + EX + JF + "ups" + JF + "End" + wanted = """haupsblEnd""" +class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteFirst(_VimTest): + snippets = ("test", """h${1:a$2b}l""") + keys = "test" + EX + "ups" + JF + "End" + wanted = """hupslEnd""" +class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackOverwrite(_VimTest): + snippets = ("test", """h${1:a$2b}l""") + keys = "test" + EX + JF + "longertext" + JB + "overwrite" + JF + "End" + wanted = """hoverwritelEnd""" +class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackAndForward0(_VimTest): + snippets = ("test", """h${1:a$2b}l""") + keys = "test" + EX + JF + "longertext" + JB + JF + "overwrite" + JF + "End" + wanted = """haoverwriteblEnd""" +class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackAndForward1(_VimTest): + snippets = ("test", """h${1:a$2b}l""") + keys = "test" + EX + JF + "longertext" + JB + JF + JF + "End" + wanted = """halongertextblEnd""" + +class TabStop_TSInDefaultNested_OverwriteOneJumpBackToOther(_VimTest): + snippets = ("test", "hi ${1:this ${2:second ${3:third}}} $4") + keys = "test" + EX + JF + "Hallo" + JF + "Ende" + wanted = "hi this Hallo Ende" +class TabStop_TSInDefaultNested_OverwriteOneJumpToThird(_VimTest): + snippets = ("test", "hi ${1:this ${2:second ${3:third}}} $4") + keys = "test" + EX + JF + JF + "Hallo" + JF + "Ende" + wanted = "hi this second Hallo Ende" +class TabStop_TSInDefaultNested_OverwriteOneJumpAround(_VimTest): + snippets = ("test", "hi ${1:this ${2:second ${3:third}}} $4") + keys = "test" + EX + JF + JF + "Hallo" + JB+JB + "Blah" + JF + "Ende" + wanted = "hi Blah Ende" + +class TabStop_TSInDefault_MirrorsOutside_DoNothing(_VimTest): + snippets = ("test", "hi ${1:this ${2:second}} $2") + keys = "test" + EX + wanted = "hi this second second" +class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond(_VimTest): + snippets = ("test", "hi ${1:this ${2:second}} $2") + keys = "test" + EX + JF + "Hallo" + wanted = "hi this Hallo Hallo" +class TabStop_TSInDefault_MirrorsOutside_Overwrite0(_VimTest): + snippets = ("test", "hi ${1:this ${2:second}} $2") + keys = "test" + EX + "Hallo" + wanted = "hi Hallo " +class TabStop_TSInDefault_MirrorsOutside_Overwrite1(_VimTest): + snippets = ("test", "$1: ${1:'${2:second}'} $2") + keys = "test" + EX + "Hallo" + wanted = "Hallo: Hallo " +class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond1(_VimTest): + snippets = ("test", "$1: ${1:'${2:second}'} $2") + keys = "test" + EX + JF + "Hallo" + wanted = "'Hallo': 'Hallo' Hallo" +class TabStop_TSInDefault_MirrorsOutside_OverwriteFirstSwitchNumbers(_VimTest): + snippets = ("test", "$2: ${2:'${1:second}'} $1") + keys = "test" + EX + "Hallo" + wanted = "'Hallo': 'Hallo' Hallo" +class TabStop_TSInDefault_MirrorsOutside_OverwriteFirst_RLExample(_VimTest): + snippets = ("test", """`!p snip.rv = t[1].split('/')[-1].lower().strip("'")` = require(${1:'${2:sys}'})""") + keys = "test" + EX + "WORLD" + JF + "End" + wanted = "world = require(WORLD)End" +class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond_RLExample(_VimTest): + snippets = ("test", """`!p snip.rv = t[1].split('/')[-1].lower().strip("'")` = require(${1:'${2:sys}'})""") + keys = "test" + EX + JF + "WORLD" + JF + "End" + wanted = "world = require('WORLD')End" + +class TabStop_Multiline_Leave(_VimTest): + snippets = ("test", "hi ${1:first line\nsecond line} world" ) + keys = "test" + EX + wanted = "hi first line\nsecond line world" +class TabStop_Multiline_Overwrite(_VimTest): + snippets = ("test", "hi ${1:first line\nsecond line} world" ) + keys = "test" + EX + "Nothing" + wanted = "hi Nothing world" +class TabStop_Multiline_MirrorInFront_Leave(_VimTest): + snippets = ("test", "hi $1 ${1:first line\nsecond line} world" ) + keys = "test" + EX + wanted = "hi first line\nsecond line first line\nsecond line world" +class TabStop_Multiline_MirrorInFront_Overwrite(_VimTest): + snippets = ("test", "hi $1 ${1:first line\nsecond line} world" ) + keys = "test" + EX + "Nothing" + wanted = "hi Nothing Nothing world" +class TabStop_Multiline_DelFirstOverwriteSecond_Overwrite(_VimTest): + snippets = ("test", "hi $1 $2 ${1:first line\nsecond line} ${2:Hi} world" ) + keys = "test" + EX + BS + JF + "Nothing" + wanted = "hi Nothing Nothing world" + +class TabStopNavigatingInInsertModeSimple_ExpectCorrectResult(_VimTest): + snippets = ("hallo", "Hallo ${1:WELT} ups") + keys = "hallo" + EX + "haselnut" + 2*ARR_L + "hips" + JF + "end" + wanted = "Hallo haselnhipsut upsend" + +class TabStop_CROnlyOnSelectedNear(_VimTest): + snippets = ("test", "t$1t${2: }t{\n\t$0\n}") + keys = "test" + EX + JF + "\n" + JF + "t" + wanted = "tt\nt{\n\tt\n}" diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Transformation.py b/vim/vim.symlink/bundle/ultisnips/test/test_Transformation.py new file mode 100644 index 0000000..0dd7b73 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Transformation.py @@ -0,0 +1,172 @@ +# encoding: utf-8 +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * +from test.util import no_unidecode_available + +# Transformations {{{# +class Transformation_SimpleCase_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/foo/batzl/}") + keys = "test" + EX + "hallo foo boy" + wanted = "hallo foo boy hallo batzl boy" +class Transformation_SimpleCaseNoTransform_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/foo/batzl/}") + keys = "test" + EX + "hallo" + wanted = "hallo hallo" +class Transformation_SimpleCaseTransformInFront_ExpectCorrectResult(_VimTest): + snippets = ("test", "${1/foo/batzl/} $1") + keys = "test" + EX + "hallo foo" + wanted = "hallo batzl hallo foo" +class Transformation_SimpleCaseTransformInFrontDefVal_ECR(_VimTest): + snippets = ("test", "${1/foo/batzl/} ${1:replace me}") + keys = "test" + EX + "hallo foo" + wanted = "hallo batzl hallo foo" +class Transformation_MultipleTransformations_ECR(_VimTest): + snippets = ("test", "${1:Some Text}${1/.+/\\U$0\E/}\n${1/.+/\L$0\E/}") + keys = "test" + EX + "SomE tExt " + wanted = "SomE tExt SOME TEXT \nsome text " +class Transformation_TabIsAtEndAndDeleted_ECR(_VimTest): + snippets = ("test", "${1/.+/is something/}${1:some}") + keys = "hallo test" + EX + "some\b\b\b\b\b" + wanted = "hallo " +class Transformation_TabIsAtEndAndDeleted1_ECR(_VimTest): + snippets = ("test", "${1/.+/is something/}${1:some}") + keys = "hallo test" + EX + "some\b\b\b\bmore" + wanted = "hallo is somethingmore" +class Transformation_TabIsAtEndNoTextLeave_ECR(_VimTest): + snippets = ("test", "${1/.+/is something/}${1}") + keys = "hallo test" + EX + wanted = "hallo " +class Transformation_TabIsAtEndNoTextType_ECR(_VimTest): + snippets = ("test", "${1/.+/is something/}${1}") + keys = "hallo test" + EX + "b" + wanted = "hallo is somethingb" +class Transformation_InsideTabLeaveAtDefault_ECR(_VimTest): + snippets = ("test", r"$1 ${2:${1/.+/(?0:defined $0)/}}") + keys = "test" + EX + "sometext" + JF + wanted = "sometext defined sometext" +class Transformation_InsideTabOvertype_ECR(_VimTest): + snippets = ("test", r"$1 ${2:${1/.+/(?0:defined $0)/}}") + keys = "test" + EX + "sometext" + JF + "overwrite" + wanted = "sometext overwrite" + + +class Transformation_Backreference_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/([ab])oo/$1ull/}") + keys = "test" + EX + "foo boo aoo" + wanted = "foo boo aoo foo bull aoo" +class Transformation_BackreferenceTwice_ExpectCorrectResult(_VimTest): + snippets = ("test", r"$1 ${1/(dead) (par[^ ]*)/this $2 is a bit $1/}") + keys = "test" + EX + "dead parrot" + wanted = "dead parrot this parrot is a bit dead" + +class Transformation_CleverTransformUpercaseChar_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(.)/\\u$1/}") + keys = "test" + EX + "hallo" + wanted = "hallo Hallo" +class Transformation_CleverTransformLowercaseChar_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(.*)/\l$1/}") + keys = "test" + EX + "Hallo" + wanted = "Hallo hallo" +class Transformation_CleverTransformLongUpper_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(.*)/\\U$1\E/}") + keys = "test" + EX + "hallo" + wanted = "hallo HALLO" +class Transformation_CleverTransformLongLower_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(.*)/\L$1\E/}") + keys = "test" + EX + "HALLO" + wanted = "HALLO hallo" + +class Transformation_SimpleCaseAsciiResult(_VimTest): + skip_if = lambda self: no_unidecode_available() + snippets = ("ascii", "$1 ${1/(.*)/$1/a}") + keys = "ascii" + EX + "éèàçôïÉÈÀÇÔÏ€" + wanted = "éèàçôïÉÈÀÇÔÏ€ eeacoiEEACOIEU" +class Transformation_LowerCaseAsciiResult(_VimTest): + skip_if = lambda self: no_unidecode_available() + snippets = ("ascii", "$1 ${1/(.*)/\L$1\E/a}") + keys = "ascii" + EX + "éèàçôïÉÈÀÇÔÏ€" + wanted = "éèàçôïÉÈÀÇÔÏ€ eeacoieeacoieu" + +class Transformation_ConditionalInsertionSimple_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(^a).*/(?0:began with an a)/}") + keys = "test" + EX + "a some more text" + wanted = "a some more text began with an a" +class Transformation_CIBothDefinedNegative_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(?:(^a)|(^b)).*/(?1:yes:no)/}") + keys = "test" + EX + "b some" + wanted = "b some no" +class Transformation_CIBothDefinedPositive_ExpectCorrectResult(_VimTest): + snippets = ("test", "$1 ${1/(?:(^a)|(^b)).*/(?1:yes:no)/}") + keys = "test" + EX + "a some" + wanted = "a some yes" +class Transformation_ConditionalInsertRWEllipsis_ECR(_VimTest): + snippets = ("test", r"$1 ${1/(\w+(?:\W+\w+){,7})\W*(.+)?/$1(?2:...)/}") + keys = "test" + EX + "a b c d e f ghhh h oha" + wanted = "a b c d e f ghhh h oha a b c d e f ghhh h..." +class Transformation_ConditionalInConditional_ECR(_VimTest): + snippets = ("test", r"$1 ${1/^.*?(-)?(>)?$/(?2::(?1:>:.))/}") + keys = "test" + EX + "hallo" + ESC + "$a\n" + \ + "test" + EX + "hallo-" + ESC + "$a\n" + \ + "test" + EX + "hallo->" + wanted = "hallo .\nhallo- >\nhallo-> " + +class Transformation_CINewlines_ECR(_VimTest): + snippets = ("test", r"$1 ${1/, */\n/}") + keys = "test" + EX + "test, hallo" + wanted = "test, hallo test\nhallo" +class Transformation_CITabstop_ECR(_VimTest): + snippets = ("test", r"$1 ${1/, */\t/}") + keys = "test" + EX + "test, hallo" + wanted = "test, hallo test\thallo" +class Transformation_CIEscapedParensinReplace_ECR(_VimTest): + snippets = ("test", r"$1 ${1/hal((?:lo)|(?:ul))/(?1:ha\($1\))/}") + keys = "test" + EX + "test, halul" + wanted = "test, halul test, ha(ul)" + +class Transformation_OptionIgnoreCase_ECR(_VimTest): + snippets = ("test", r"$1 ${1/test/blah/i}") + keys = "test" + EX + "TEST" + wanted = "TEST blah" +class Transformation_OptionReplaceGlobal_ECR(_VimTest): + snippets = ("test", r"$1 ${1/, */-/g}") + keys = "test" + EX + "a, nice, building" + wanted = "a, nice, building a-nice-building" +class Transformation_OptionReplaceGlobalMatchInReplace_ECR(_VimTest): + snippets = ("test", r"$1 ${1/, */, /g}") + keys = "test" + EX + "a, nice, building" + wanted = "a, nice, building a, nice, building" +class TransformationUsingBackspaceToDeleteDefaultValueInFirstTab_ECR(_VimTest): + snippets = ("test", "snip ${1/.+/(?0:m1)/} ${2/.+/(?0:m2)/} " + "${1:default} ${2:def}") + keys = "test" + EX + BS + JF + "hi" + wanted = "snip m2 hi" +class TransformationUsingBackspaceToDeleteDefaultValueInSecondTab_ECR(_VimTest): + snippets = ("test", "snip ${1/.+/(?0:m1)/} ${2/.+/(?0:m2)/} " + "${1:default} ${2:def}") + keys = "test" + EX + "hi" + JF + BS + wanted = "snip m1 hi " +class TransformationUsingBackspaceToDeleteDefaultValueTypeSomethingThen_ECR(_VimTest): + snippets = ("test", "snip ${1/.+/(?0:matched)/} ${1:default}") + keys = "test" + EX + BS + "hallo" + wanted = "snip matched hallo" +class TransformationUsingBackspaceToDeleteDefaultValue_ECR(_VimTest): + snippets = ("test", "snip ${1/.+/(?0:matched)/} ${1:default}") + keys = "test" + EX + BS + wanted = "snip " +class Transformation_TestKill_InsertBefore_NoKill(_VimTest): + snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" + keys = "hallo test" + EX + "AUCH" + ESC + "wihi" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noAUCH hinoauchnoauch_end" +class Transformation_TestKill_InsertAfter_NoKill(_VimTest): + snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" + keys = "hallo test" + EX + "AUCH" + ESC + "eiab" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noAUCH noauchnoauchab_end" +class Transformation_TestKill_InsertBeginning_Kill(_VimTest): + snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" + keys = "hallo test" + EX + "AUCH" + ESC + "wahi" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noAUCH ahiuchauch_end" +class Transformation_TestKill_InsertEnd_Kill(_VimTest): + snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" + keys = "hallo test" + EX + "AUCH" + ESC + "ehihi" + ESC + "bb" + "ino" + JF + "end" + wanted = "hallo noAUCH auchauchih_end" +# End: Transformations #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_UltiSnipFunc.py b/vim/vim.symlink/bundle/ultisnips/test/test_UltiSnipFunc.py new file mode 100644 index 0000000..510130d --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_UltiSnipFunc.py @@ -0,0 +1,142 @@ +# encoding: utf-8 +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * +from test.util import running_on_windows + +# AddSnippet Function {{{# +class _AddFuncBase(_VimTest): + args = "" + def _extra_options_pre_init(self, vim_config): + vim_config.append(":call UltiSnips#AddSnippetWithPriority(%s)" % + self.args) + +class AddFunc_Simple(_AddFuncBase): + args = '"test", "simple expand", "desc", "", "all", 0' + keys = "abc test" + EX + wanted = "abc simple expand" + +class AddFunc_Opt(_AddFuncBase): + args = '".*test", "simple expand", "desc", "r", "all", 0' + keys = "abc test" + EX + wanted = "simple expand" +# End: AddSnippet Function #}}} + +# Langmap Handling {{{# +# Test for bug 501727 # +class TestNonEmptyLangmap_ExpectCorrectResult(_VimTest): + snippets = ("testme", +"""my snipped ${1:some_default} +and a mirror: $1 +$2...$3 +$0""") + keys = "testme" + EX + "hi1" + JF + "hi2" + JF + "hi3" + JF + "hi4" + wanted ="""my snipped hi1 +and a mirror: hi1 +hi2...hi3 +hi4""" + def _extra_options_pre_init(self, vim_config): + vim_config.append("set langmap=dj,rk,nl,ln,jd,kr,DJ,RK,NL,LN,JD,KR") + +# Test for https://bugs.launchpad.net/bugs/501727 # +class TestNonEmptyLangmapWithSemi_ExpectCorrectResult(_VimTest): + snippets = ("testme", +"""my snipped ${1:some_default} +and a mirror: $1 +$2...$3 +$0""") + keys = "testme" + EX + "hi;" + JF + "hi2" + JF + "hi3" + JF + "hi4" + ESC + ";Hello" + wanted ="""my snipped hi; +and a mirror: hi; +hi2...hi3 +hi4Hello""" + + def _before_test(self): + self.vim.send(":set langmap=\\\\;;A\n") + +# Test for bug 871357 # +class TestLangmapWithUtf8_ExpectCorrectResult(_VimTest): + skip_if = lambda self: running_on_windows() # SendKeys can't send UTF characters + snippets = ("testme", +"""my snipped ${1:some_default} +and a mirror: $1 +$2...$3 +$0""") + keys = "testme" + EX + "hi1" + JF + "hi2" + JF + "hi3" + JF + "hi4" + wanted ="""my snipped hi1 +and a mirror: hi1 +hi2...hi3 +hi4""" + + def _before_test(self): + self.vim.send(":set langmap=йq,цw,уe,кr,еt,нy,гu,шi,щo,зp,х[,ъ],фa,ыs,вd,аf,пg,рh,оj,лk,дl,ж\\;,э',яz,чx,сc,мv,иb,тn,ьm,ю.,ё',ЙQ,ЦW,УE,КR,ЕT,НY,ГU,ШI,ЩO,ЗP,Х\{,Ъ\},ФA,ЫS,ВD,АF,ПG,РH,ОJ,ЛK,ДL,Ж\:,Э\",ЯZ,ЧX,СC,МV,ИB,ТN,ЬM,Б\<,Ю\>\n") + +# End: Langmap Handling #}}} + +# SnippetsInCurrentScope {{{# +class VerifyVimDict1(_VimTest): + """check: + correct type (4 means vim dictionary) + correct length of dictionary (in this case we have on element if the use same prefix, dictionary should have 1 element) + correct description (including the apostrophe) + if the prefix is mismatched no resulting dict should have 0 elements + """ + + snippets = ('testâ', 'abc123ά', '123\'êabc') + keys = ('test=(type(UltiSnips#SnippetsInCurrentScope()) . len(UltiSnips#SnippetsInCurrentScope()) . ' + + 'UltiSnips#SnippetsInCurrentScope()["testâ"]' + ')\n' + + '=len(UltiSnips#SnippetsInCurrentScope())\n') + + wanted = 'test41123\'êabc0' + +class VerifyVimDict2(_VimTest): + """check: + can use " in trigger + """ + + snippets = ('te"stâ', 'abc123ά', '123êabc') + akey = "'te{}stâ'".format('"') + keys = ('te"=(UltiSnips#SnippetsInCurrentScope()[{}]'.format(akey) + ')\n') + wanted = 'te"123êabc' + +class VerifyVimDict3(_VimTest): + """check: + can use ' in trigger + """ + + snippets = ("te'stâ", 'abc123ά', '123êabc') + akey = '"te{}stâ"'.format("'") + keys = ("te'=(UltiSnips#SnippetsInCurrentScope()[{}]".format(akey) + ')\n') + wanted = "te'123êabc" +# End: SnippetsInCurrentScope #}}} + +# Snippet Source {{{# +class AddNewSnippetSource(_VimTest): + keys = ( "blumba" + EX + ESC + + ":%(python)s UltiSnips_Manager.register_snippet_source(" + + "'temp', MySnippetSource())\n" + + "oblumba" + EX + ESC + + ":%(python)s UltiSnips_Manager.unregister_snippet_source('temp')\n" + + "oblumba" + EX ) % { 'python': 'py3' if PYTHON3 else 'py' } + wanted = ( + "blumba" + EX + "\n" + + "this is a dynamic snippet" + "\n" + + "blumba" + EX + ) + + def _extra_options_post_init(self, vim_config): + self._create_file("snippet_source.py",""" +from UltiSnips.snippet.source import SnippetSource +from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition + +class MySnippetSource(SnippetSource): + def get_snippets(self, filetypes, before, possible): + if before.endswith('blumba'): + return [ + UltiSnipsSnippetDefinition( + -100, "blumba", "this is a dynamic snippet", "", "", {}, "blub") + ] + return [] +""") + pyfile = 'py3file' if PYTHON3 else 'pyfile' + vim_config.append("%s %s" % (pyfile, self.name_temp("snippet_source.py"))) +# End: Snippet Source #}}} diff --git a/vim/vim.symlink/bundle/ultisnips/test/test_Visual.py b/vim/vim.symlink/bundle/ultisnips/test/test_Visual.py new file mode 100644 index 0000000..7e31e9c --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/test_Visual.py @@ -0,0 +1,141 @@ +from test.vim_test_case import VimTestCase as _VimTest +from test.constant import * + +# ${VISUAL} {{{# +class Visual_NoVisualSelection_Ignore(_VimTest): + snippets = ("test", "h${VISUAL}b") + keys = "test" + EX + "abc" + wanted = "hbabc" +class Visual_SelectOneWord(_VimTest): + snippets = ("test", "h${VISUAL}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + wanted = "hblablubb" +class Visual_SelectOneWord_ProblemAfterTab(_VimTest): + snippets = ("test", "h${VISUAL}b", "", "i") + keys = "\tblablub" + ESC + "5hv3l" + EX + "test" + EX + wanted = "\tbhlablbub" +class VisualWithDefault_ExpandWithoutVisual(_VimTest): + snippets = ("test", "h${VISUAL:world}b") + keys = "test" + EX + "hi" + wanted = "hworldbhi" +class VisualWithDefaultWithSlashes_ExpandWithoutVisual(_VimTest): + snippets = ("test", r"h${VISUAL:\/\/ body}b") + keys = "test" + EX + "hi" + wanted = "h// bodybhi" +class VisualWithDefault_ExpandWithVisual(_VimTest): + snippets = ("test", "h${VISUAL:world}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + wanted = "hblablubb" + +class Visual_ExpandTwice(_VimTest): + snippets = ("test", "h${VISUAL}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + "\ntest" + EX + wanted = "hblablubb\nhb" + +class Visual_SelectOneWord_TwiceVisual(_VimTest): + snippets = ("test", "h${VISUAL}b${VISUAL}a") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + wanted = "hblablubbblabluba" +class Visual_SelectOneWord_Inword(_VimTest): + snippets = ("test", "h${VISUAL}b", "Description", "i") + keys = "blablub" + ESC + "0lv4l" + EX + "test" + EX + wanted = "bhlablubb" +class Visual_SelectOneWord_TillEndOfLine(_VimTest): + snippets = ("test", "h${VISUAL}b", "Description", "i") + keys = "blablub" + ESC + "0v$" + EX + "test" + EX + ESC + "o" + wanted = "hblablub\nb" +class Visual_SelectOneWordWithTabstop_TillEndOfLine(_VimTest): + snippets = ("test", "h${2:ahh}${VISUAL}${1:ups}b", "Description", "i") + keys = "blablub" + ESC + "0v$" + EX + "test" + EX + "mmm" + JF + "n" + JF + "done" + ESC + "o" + wanted = "hnblablub\nmmmbdone" +class Visual_InDefaultText_SelectOneWord_NoOverwrite(_VimTest): + snippets = ("test", "h${1:${VISUAL}}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + JF + "hello" + wanted = "hblablubbhello" +class Visual_InDefaultText_SelectOneWord(_VimTest): + snippets = ("test", "h${1:${VISUAL}}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + "hello" + wanted = "hhellob" + +class Visual_CrossOneLine(_VimTest): + snippets = ("test", "h${VISUAL}b") + keys = "bla blub\n helloi" + ESC + "0k4lvjll" + EX + "test" + EX + wanted = "bla hblub\n hellobi" + +class Visual_LineSelect_Simple(_VimTest): + snippets = ("test", "h${VISUAL}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + wanted = "hhello\n nice\n worldb" +class Visual_InDefaultText_LineSelect_NoOverwrite(_VimTest): + snippets = ("test", "h${1:bef${VISUAL}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" + wanted = "hbefhello\n nice\n worldaftbhi" +class Visual_InDefaultText_LineSelect_Overwrite(_VimTest): + snippets = ("test", "h${1:bef${VISUAL}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "jup" + JF + "hi" + wanted = "hjupbhi" +class Visual_LineSelect_CheckIndentSimple(_VimTest): + snippets = ("test", "beg\n\t${VISUAL}\nend") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + wanted = "beg\n\thello\n\tnice\n\tworld\nend" +class Visual_LineSelect_CheckIndentTwice(_VimTest): + snippets = ("test", "beg\n\t${VISUAL}\nend") + keys = " hello\n nice\n\tworld" + ESC + "Vkk" + EX + "test" + EX + wanted = "beg\n\t hello\n\t nice\n\t\tworld\nend" +class Visual_InDefaultText_IndentSpacesToTabstop_NoOverwrite(_VimTest): + snippets = ("test", "h${1:beforea${VISUAL}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" + wanted = "hbeforeahello\n\tnice\n\tworldaftbhi" +class Visual_InDefaultText_IndentSpacesToTabstop_Overwrite(_VimTest): + snippets = ("test", "h${1:beforea${VISUAL}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "ups" + JF + "hi" + wanted = "hupsbhi" +class Visual_InDefaultText_IndentSpacesToTabstop_NoOverwrite1(_VimTest): + snippets = ("test", "h${1:beforeaaa${VISUAL}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" + wanted = "hbeforeaaahello\n\t nice\n\t worldaftbhi" +class Visual_InDefaultText_IndentBeforeTabstop_NoOverwrite(_VimTest): + snippets = ("test", "hello\n\t ${1:${VISUAL}}\nend") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" + wanted = "hello\n\t hello\n\t nice\n\t world\nendhi" + +class Visual_LineSelect_WithTabStop(_VimTest): + snippets = ("test", "beg\n\t${VISUAL}\n\t${1:here_we_go}\nend") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "super" + JF + "done" + wanted = "beg\n\thello\n\tnice\n\tworld\n\tsuper\nenddone" +class Visual_LineSelect_CheckIndentWithTS_NoOverwrite(_VimTest): + snippets = ("test", "beg\n\t${0:${VISUAL}}\nend") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + wanted = "beg\n\thello\n\tnice\n\tworld\nend" +class Visual_LineSelect_DedentLine(_VimTest): + snippets = ("if", "if {\n\t${VISUAL}$0\n}") + keys = "if" + EX + "one\n\ttwo\n\tthree" + ESC + ARR_U*2 + "V" + ARR_D + EX + "\tif" + EX + wanted = "if {\n\tif {\n\t\tone\n\t\ttwo\n\t}\n\tthree\n}" + +class VisualTransformation_SelectOneWord(_VimTest): + snippets = ("test", r"h${VISUAL/./\U$0\E/g}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + wanted = "hBLABLUBb" +class VisualTransformationWithDefault_ExpandWithoutVisual(_VimTest): + snippets = ("test", r"h${VISUAL:world/./\U$0\E/g}b") + keys = "test" + EX + "hi" + wanted = "hWORLDbhi" +class VisualTransformationWithDefault_ExpandWithVisual(_VimTest): + snippets = ("test", r"h${VISUAL:world/./\U$0\E/g}b") + keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + wanted = "hBLABLUBb" +class VisualTransformation_LineSelect_Simple(_VimTest): + snippets = ("test", r"h${VISUAL/./\U$0\E/g}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + wanted = "hHELLO\n NICE\n WORLDb" +class VisualTransformation_InDefaultText_LineSelect_NoOverwrite(_VimTest): + snippets = ("test", r"h${1:bef${VISUAL/./\U$0\E/g}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" + wanted = "hbefHELLO\n NICE\n WORLDaftbhi" +class VisualTransformation_InDefaultText_LineSelect_Overwrite(_VimTest): + snippets = ("test", r"h${1:bef${VISUAL/./\U$0\E/g}aft}b") + keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "jup" + JF + "hi" + wanted = "hjupbhi" + +# End: ${VISUAL} #}}} + diff --git a/vim/vim.symlink/bundle/ultisnips/test/util.py b/vim/vim.symlink/bundle/ultisnips/test/util.py new file mode 100644 index 0000000..be32c34 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/util.py @@ -0,0 +1,15 @@ +import platform + +try: + import unidecode + UNIDECODE_IMPORTED = True +except ImportError: + UNIDECODE_IMPORTED = False + +def running_on_windows(): + if platform.system() == "Windows": + return "Does not work on Windows." + +def no_unidecode_available(): + if not UNIDECODE_IMPORTED: + return "unidecode is not available." diff --git a/vim/vim.symlink/bundle/ultisnips/test/vim_interface.py b/vim/vim.symlink/bundle/ultisnips/test/vim_interface.py new file mode 100644 index 0000000..c673478 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/vim_interface.py @@ -0,0 +1,247 @@ +# encoding: utf-8 + +import os +import re +import subprocess +import tempfile +import textwrap +import time + +from test.constant import * + +def wait_until_file_exists(file_path, times=None, interval=0.01): + while times is None or times: + if os.path.exists(file_path): + return True + time.sleep(interval) + if times is not None: + times -= 1 + return False + +def read_text_file(filename): + """Reads the contens of a text file.""" + if PYTHON3: + return open(filename,"r", encoding="utf-8").read() + else: + return open(filename,"r").read() + + +def is_process_running(pid): + """Returns true if a process with pid is running, false otherwise.""" + # from http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + +def silent_call(cmd): + """Calls 'cmd' and returns the exit value.""" + return subprocess.call(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + +def create_directory(dirname): + """Creates 'dirname' and its parents if it does not exist.""" + try: + os.makedirs(dirname) + except OSError: + pass + + +class TempFileManager(object): + def __init__(self, name=""): + self._temp_dir = tempfile.mkdtemp(prefix="UltiSnipsTest_" + name) + + def name_temp(self, file_path): + return os.path.join(self._temp_dir, file_path) + + def write_temp(self, file_path, content): + abs_path = self.name_temp(file_path) + create_directory(os.path.dirname(abs_path)) + if PYTHON3: + with open(abs_path, "w", encoding="utf-8") as f: + f.write(content) + else: + with open(abs_path, "w") as f: + f.write(content) + return abs_path + + def unique_name_temp(self, suffix="", prefix=""): + file_handler, abspath = tempfile.mkstemp(suffix, prefix, self._temp_dir) + os.close(file_handler) + os.remove(abspath) + return abspath + + def clear_temp(self): + shutil.rmtree(self._temp_dir) + create_directory(self._temp_dir) + + +class VimInterface(TempFileManager): + def __init__(self, name=""): + TempFileManager.__init__(self, name) + + def get_buffer_data(self): + buffer_path = self.unique_name_temp(prefix="buffer_") + self.send(ESC + ":w! %s\n" % buffer_path) + if wait_until_file_exists(buffer_path, 50): + return read_text_file(buffer_path)[:-1] + + def send(self, s): + raise NotImplementedError() + + def launch(self, config=[]): + pid_file = self.name_temp("vim.pid") + done_file = self.name_temp("loading_done") + if os.path.exists(done_file): + os.remove(done_file) + + post_config = [] + post_config.append("%s << EOF" % ("py3" if PYTHON3 else "py")) + post_config.append("import vim") + post_config.append("with open('%s', 'w') as pid_file: pid_file.write(vim.eval('getpid()'))" % pid_file) + post_config.append("with open('%s', 'w') as done_file: pass" % done_file) + post_config.append("EOF") + + config_path = self.write_temp("vim_config.vim", + textwrap.dedent(os.linesep.join(config + post_config) + "\n")) + + # Note the space to exclude it from shell history. + self.send(""" vim -u %s\r\n""" % config_path) + wait_until_file_exists(done_file) + self._vim_pid = int(open(pid_file, "r").read()) + + def leave_with_wait(self): + self.send(3*ESC + ":qa!\n") + while is_process_running(self._vim_pid): + time.sleep(.05) + + +class VimInterfaceScreen(VimInterface): + def __init__(self, session): + VimInterface.__init__(self, "Screen") + self.session = session + self.need_screen_escapes = 0 + self.detect_parsing() + + def send(self, s): + if self.need_screen_escapes: + # escape characters that are special to some versions of screen + repl = lambda m: '\\' + m.group(0) + s = re.sub( r"[$^#\\']", repl, s ) + + if PYTHON3: + s = s.encode("utf-8") + + while True: + rv = 0 + if len(s) > 30: + rv |= silent_call(["screen", "-x", self.session, "-X", "register", "S", s]) + rv |= silent_call(["screen", "-x", self.session, "-X", "paste", "S"]) + else: + rv |= silent_call(["screen", "-x", self.session, "-X", "stuff", s]) + if not rv: break + time.sleep(.2) + + def detect_parsing(self): + self.launch() + # Send a string where the interpretation will depend on version of screen + string = "$TERM" + self.send("i" + string + ESC) + output = self.get_buffer_data() + # If the output doesn't match the input, need to do additional escaping + if output != string: + self.need_screen_escapes = 1 + self.leave_with_wait() + +class VimInterfaceTmux(VimInterface): + def __init__(self, session): + VimInterface.__init__(self, "Tmux") + self.session = session + self._check_version() + + def send(self, s): + # I did not find any documentation on what needs escaping when sending + # to tmux, but it seems like this is all that is needed for now. + s = s.replace(';', r'\;') + + if PYTHON3: + s = s.encode("utf-8") + silent_call(["tmux", "send-keys", "-t", self.session, "-l", s]) + + def _check_version(self): + stdout, _ = subprocess.Popen(["tmux", "-V"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + if PYTHON3: + stdout = stdout.decode("utf-8") + m = re.match(r"tmux (\d+).(\d+)", stdout) + if not m or not (int(m.group(1)), int(m.group(2))) >= (1, 8): + raise RuntimeError("Need at least tmux 1.8, you have %s." % stdout.strip()) + +class VimInterfaceWindows(VimInterface): + BRACES = re.compile("([}{])") + WIN_ESCAPES = ["+", "^", "%", "~", "[", "]", "<", ">", "(", ")"] + WIN_REPLACES = [ + (BS, "{BS}"), + (ARR_L, "{LEFT}"), + (ARR_R, "{RIGHT}"), + (ARR_U, "{UP}"), + (ARR_D, "{DOWN}"), + ("\t", "{TAB}"), + ("\n", "~"), + (ESC, "{ESC}"), + + # On my system ` waits for a second keystroke, so `+SPACE = "`". On + # most systems, `+Space = "` ". I work around this, by sending the host + # ` as `+_+BS. Awkward, but the only way I found to get this working. + ("`", "`_{BS}"), + ("´", "´_{BS}"), + ("{^}", "{^}_{BS}"), + ] + + def __init__(self): + self.seq_buf = [] + # import windows specific modules + import win32com.client, win32gui + self.win32gui = win32gui + self.shell = win32com.client.Dispatch("WScript.Shell") + + def is_focused(self, title=None): + cur_title = self.win32gui.GetWindowText(self.win32gui.GetForegroundWindow()) + if (title or "- GVIM") in cur_title: + return True + return False + + def focus(self, title=None): + if not self.shell.AppActivate(title or "- GVIM"): + raise Exception("Failed to switch to GVim window") + time.sleep(1) + + def convert_keys(self, keys): + keys = self.BRACES.sub(r"{\1}", keys) + for k in self.WIN_ESCAPES: + keys = keys.replace(k, "{%s}" % k) + for f, r in self.WIN_REPLACES: + keys = keys.replace(f, r) + return keys + + def send(self, keys): + self.seq_buf.append(keys) + seq = "".join(self.seq_buf) + + for f in SEQUENCES: + if f.startswith(seq) and f != seq: + return + self.seq_buf = [] + + seq = self.convert_keys(seq) + + if not self.is_focused(): + time.sleep(2) + self.focus() + if not self.is_focused(): + # This is the only way I can find to stop test execution + raise KeyboardInterrupt("Failed to focus GVIM") + + self.shell.SendKeys(seq) + diff --git a/vim/vim.symlink/bundle/ultisnips/test/vim_test_case.py b/vim/vim.symlink/bundle/ultisnips/test/vim_test_case.py new file mode 100644 index 0000000..43ca61a --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test/vim_test_case.py @@ -0,0 +1,423 @@ +# encoding: utf-8 + +# pylint: skip-file + +import os +import re +import shutil +import subprocess +import sys +import tempfile +import textwrap +import time +import unittest + +from constant import * + +def is_process_running(pid): + """Returns true if a process with pid is running, false otherwise.""" + # from http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + +def silent_call(cmd): + """Calls 'cmd' and returns the exit value.""" + return subprocess.call(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + +def create_directory(dirname): + """Creates 'dirname' and its parents if it does not exist.""" + try: + os.makedirs(dirname) + except OSError: + pass + +def plugin_cache_dir(): + """The directory that we check out our bundles to.""" + return os.path.join(tempfile.gettempdir(), "UltiSnips_test_vim_plugins") + +def read_text_file(filename): + """Reads the contens of a text file.""" + if PYTHON3: + return open(filename,"r", encoding="utf-8").read() + else: + return open(filename,"r").read() + +def wait_until_file_exists(file_path, times=None, interval=0.01): + while times is None or times: + if os.path.exists(file_path): + return True + time.sleep(interval) + if times is not None: + times -= 1 + return False + +class TempFileManager(object): + """A TempFileManager keeps a unique prefix path for temp + files. A temp file, or a name for a temp file generate by a + TempFileManager always belongs to the same directory. + """ + def __init__(self, name=""): + """The unique prefix path is UltiSnipsTest_{name}XXXXXX. + """ + self._temp_dir = tempfile.mkdtemp(prefix="UltiSnipsTest_" + name) + + def name_temp(self, file_path): + """Get the absolute path of a temp file by given file path. + """ + return os.path.join(self._temp_dir, file_path) + + def write_temp(self, file_path, content): + """Write the content to a temp file by given file path inside + the _temp_dir, and return the absolute path of that file. + """ + abs_path = self.name_temp(file_path) + create_directory(os.path.dirname(abs_path)) + if PYTHON3: + with open(abs_path, "w", encoding="utf-8") as f: + f.write(content) + else: + with open(abs_path, "w") as f: + f.write(content) + return abs_path + + def unique_name_temp(self, suffix="", prefix=""): + """Generate a unique name for a temp file with given suffix and + prefix, and return full absolute path. + """ + file_handler, abspath = tempfile.mkstemp(suffix, prefix, self._temp_dir) + os.close(file_handler) + os.remove(abspath) + return abspath + + def clear_temp(self): + """Clear the temp file directory, but the directory itself is + not removed. + """ + shutil.rmtree(self._temp_dir) + create_directory(self._temp_dir) + + +class VimInterface(TempFileManager): + def __init__(self, name=""): + TempFileManager.__init__(self, name) + + def get_buffer_data(self): + buffer_path = self.unique_name_temp(prefix="buffer_") + self.send(ESC + ":w! %s\n" % buffer_path) + if wait_until_file_exists(buffer_path, 50): + return read_text_file(buffer_path)[:-1] + + def send(self, s): + raise NotImplementedError() + + def launch(self, config=[]): + pid_file = self.name_temp("vim.pid") + done_file = self.name_temp("loading_done") + if os.path.exists(done_file): + os.remove(done_file) + + post_config = [] + post_config.append("%s << EOF" % ("py3" if PYTHON3 else "py")) + post_config.append("import vim") + post_config.append("with open('%s', 'w') as pid_file: pid_file.write(vim.eval('getpid()'))" % pid_file) + post_config.append("with open('%s', 'w') as done_file: pass" % done_file) + post_config.append("EOF") + + config_path = self.write_temp("vim_config.vim", + textwrap.dedent(os.linesep.join(config + post_config) + "\n")) + + # Note the space to exclude it from shell history. + self.send(""" vim -u %s\r\n""" % config_path) + wait_until_file_exists(done_file) + self._vim_pid = int(open(pid_file, "r").read()) + + def leave_with_wait(self): + self.send(3*ESC + ":qa!\n") + while is_process_running(self._vim_pid): + time.sleep(.05) + + +class VimInterfaceScreen(VimInterface): + def __init__(self, session): + VimInterface.__init__(self, "Screen") + self.session = session + self.need_screen_escapes = 0 + self.detect_parsing() + + def send(self, s): + if self.need_screen_escapes: + # escape characters that are special to some versions of screen + repl = lambda m: '\\' + m.group(0) + s = re.sub( r"[$^#\\']", repl, s ) + + if PYTHON3: + s = s.encode("utf-8") + + while True: + rv = 0 + if len(s) > 30: + rv |= silent_call(["screen", "-x", self.session, "-X", "register", "S", s]) + rv |= silent_call(["screen", "-x", self.session, "-X", "paste", "S"]) + else: + rv |= silent_call(["screen", "-x", self.session, "-X", "stuff", s]) + if not rv: break + time.sleep(.2) + + def detect_parsing(self): + self.launch() + # Send a string where the interpretation will depend on version of screen + string = "$TERM" + self.send("i" + string + ESC) + output = self.get_buffer_data() + # If the output doesn't match the input, need to do additional escaping + if output != string: + self.need_screen_escapes = 1 + self.leave_with_wait() + +class VimInterfaceTmux(VimInterface): + def __init__(self, session): + self.session = session + self._check_version() + + def send(self, s): + # I did not find any documentation on what needs escaping when sending + # to tmux, but it seems like this is all that is needed for now. + s = s.replace(';', r'\;') + + if PYTHON3: + s = s.encode("utf-8") + silent_call(["tmux", "send-keys", "-t", self.session, "-l", s]) + + def _check_version(self): + stdout, _ = subprocess.Popen(["tmux", "-V"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + if PYTHON3: + stdout = stdout.decode("utf-8") + m = re.match(r"tmux (\d+).(\d+)", stdout) + if not m or not (int(m.group(1)), int(m.group(2))) >= (1, 9): + raise RuntimeError("Need at least tmux 1.9, you have %s." % stdout.strip()) + +class VimInterfaceWindows(VimInterface): + BRACES = re.compile("([}{])") + WIN_ESCAPES = ["+", "^", "%", "~", "[", "]", "<", ">", "(", ")"] + WIN_REPLACES = [ + (BS, "{BS}"), + (ARR_L, "{LEFT}"), + (ARR_R, "{RIGHT}"), + (ARR_U, "{UP}"), + (ARR_D, "{DOWN}"), + ("\t", "{TAB}"), + ("\n", "~"), + (ESC, "{ESC}"), + + # On my system ` waits for a second keystroke, so `+SPACE = "`". On + # most systems, `+Space = "` ". I work around this, by sending the host + # ` as `+_+BS. Awkward, but the only way I found to get this working. + ("`", "`_{BS}"), + ("´", "´_{BS}"), + ("{^}", "{^}_{BS}"), + ] + + def __init__(self): + self.seq_buf = [] + # import windows specific modules + import win32com.client, win32gui + self.win32gui = win32gui + self.shell = win32com.client.Dispatch("WScript.Shell") + + def is_focused(self, title=None): + cur_title = self.win32gui.GetWindowText(self.win32gui.GetForegroundWindow()) + if (title or "- GVIM") in cur_title: + return True + return False + + def focus(self, title=None): + if not self.shell.AppActivate(title or "- GVIM"): + raise Exception("Failed to switch to GVim window") + time.sleep(1) + + def convert_keys(self, keys): + keys = self.BRACES.sub(r"{\1}", keys) + for k in self.WIN_ESCAPES: + keys = keys.replace(k, "{%s}" % k) + for f, r in self.WIN_REPLACES: + keys = keys.replace(f, r) + return keys + + def send(self, keys): + self.seq_buf.append(keys) + seq = "".join(self.seq_buf) + + for f in SEQUENCES: + if f.startswith(seq) and f != seq: + return + self.seq_buf = [] + + seq = self.convert_keys(seq) + + if not self.is_focused(): + time.sleep(2) + self.focus() + if not self.is_focused(): + # This is the only way I can find to stop test execution + raise KeyboardInterrupt("Failed to focus GVIM") + + self.shell.SendKeys(seq) + + +class VimTestCase(unittest.TestCase, TempFileManager): + snippets = () + files = {} + text_before = " --- some text before --- \n\n" + text_after = "\n\n --- some text after --- " + expected_error = "" + wanted = "" + keys = "" + sleeptime = 0.00 + output = "" + plugins = [] + # Skip this test for the given reason or None for not skipping it. + skip_if = lambda self: None + version = None # Will be set to vim --version output + + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + TempFileManager.__init__(self, "Case") + + def runTest(self): + # Only checks the output. All work is done in setUp(). + wanted = self.text_before + self.wanted + self.text_after + if self.expected_error: + self.assertRegexpMatches(self.output, self.expected_error) + return + for i in range(self.retries): + if self.output != wanted: + # Redo this, but slower + self.sleeptime += 0.02 + self.tearDown() + self.setUp() + self.assertEqual(self.output, wanted) + + def _extra_options_pre_init(self, vim_config): + """Adds extra lines to the vim_config list.""" + pass + + def _extra_options_post_init(self, vim_config): + """Adds extra lines to the vim_config list.""" + pass + + def _before_test(self): + """Send these keys before the test runs. Used for buffer local + variables and other options.""" + pass + + def _create_file(self, file_path, content): + """Creates a file in the runtimepath that is created for this test. + Returns the absolute path to the file.""" + return self.write_temp(file_path, textwrap.dedent(content + "\n")) + + def _link_file(self, source, relative_destination): + """Creates a link from 'source' to the 'relative_destination' in our temp dir.""" + absdir = self.name_temp(relative_destination) + create_directory(absdir) + os.symlink(source, os.path.join(absdir, os.path.basename(source))) + + def setUp(self): + if not VimTestCase.version: + VimTestCase.version, _ = subprocess.Popen(["vim", "--version"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + if PYTHON3: + VimTestCase.version = VimTestCase.version.decode("utf-8") + + if self.plugins and not self.test_plugins: + return self.skipTest("Not testing integration with other plugins.") + reason_for_skipping = self.skip_if() + if reason_for_skipping is not None: + return self.skipTest(reason_for_skipping) + + vim_config = [] + vim_config.append('set nocompatible') + vim_config.append('set runtimepath=$VIMRUNTIME,.,%s' % self._temp_dir) + + if self.plugins: + self._link_file(os.path.join(plugin_cache_dir(), "vim-pathogen", "autoload"), ".") + for plugin in self.plugins: + self._link_file(os.path.join(plugin_cache_dir(), os.path.basename(plugin)), "bundle") + vim_config.append("execute pathogen#infect()") + + # Vim parameters. + vim_config.append('syntax on') + vim_config.append('filetype plugin indent on') + vim_config.append('set clipboard=""') + vim_config.append('set encoding=utf-8') + vim_config.append('set fileencoding=utf-8') + vim_config.append('set buftype=nofile') + vim_config.append('set shortmess=at') + vim_config.append('let g:UltiSnipsExpandTrigger=""') + vim_config.append('let g:UltiSnipsJumpForwardTrigger="?"') + vim_config.append('let g:UltiSnipsJumpBackwardTrigger="+"') + vim_config.append('let g:UltiSnipsListSnippets="@"') + vim_config.append('let g:UltiSnipsUsePythonVersion="%i"' % (3 if PYTHON3 else 2)) + vim_config.append('let g:UltiSnipsSnippetDirectories=["us"]') + + self._extra_options_pre_init(vim_config) + + # Now activate UltiSnips. + vim_config.append('call UltiSnips#bootstrap#Bootstrap()') + + self._extra_options_post_init(vim_config) + + # Finally, add the snippets and some configuration for the test. + vim_config.append("%s << EOF" % ("py3" if PYTHON3 else "py")) + + if len(self.snippets) and not isinstance(self.snippets[0],tuple): + self.snippets = ( self.snippets, ) + for s in self.snippets: + sv, content = s[:2] + description = "" + options = "" + priority = 0 + if len(s) > 2: + description = s[2] + if len(s) > 3: + options = s[3] + if len(s) > 4: + priority = s[4] + vim_config.append("UltiSnips_Manager.add_snippet(%r, %r, %r, %r, priority=%i)" % ( + sv, content, description, options, priority)) + + # fill buffer with default text and place cursor in between. + prefilled_text = (self.text_before + self.text_after).splitlines() + vim_config.append("vim.current.buffer[:] = %r\n" % prefilled_text) + vim_config.append("vim.current.window.cursor = (max(len(vim.current.buffer)//2, 1), 0)") + + # End of python stuff. + vim_config.append("EOF") + + for name, content in self.files.items(): + self._create_file(name, content) + + self.vim.launch(vim_config) + + self._before_test() + + if not self.interrupt: + # Go into insert mode and type the keys but leave Vim some time to + # react. + for c in 'i' + self.keys: + self.vim.send(c) + time.sleep(self.sleeptime) + self.output = self.vim.get_buffer_data() + + def tearDown(self): + if self.interrupt: + print("Working directory: %s" % (self._temp_dir)) + return + self.vim.leave_with_wait() + self.clear_temp() + +# vim:fileencoding=utf-8:foldmarker={{{#,#}}}: diff --git a/vim/vim.symlink/bundle/ultisnips/test_all.py b/vim/vim.symlink/bundle/ultisnips/test_all.py new file mode 100755 index 0000000..290a01a --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/test_all.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# encoding: utf-8 +# +# To execute this test requires two terminals, one for running Vim and one +# for executing the test script. Both terminals should have their current +# working directories set to this directory (the one containing this test.py +# script). +# +# In one terminal, launch a GNU ``screen`` session named ``vim``: +# $ screen -S vim +# +# Or the following if you use ``tmux``: +# +# $ tmux new -s vim +# +# Now, from another terminal, launch the testsuite: +# $ ./test_all.py +# +# For each test, the test.py script will launch vim with a vimrc, run the test, +# compare the output and exit vim again. The keys are send using screen. +# +# NOTE: The tessuite is not working under Windows right now as I have no access +# to a windows system for fixing it. Volunteers welcome. Here are some comments +# from the last time I got the test suite running under windows. +# +# Under windows, COM's SendKeys is used to send keystrokes to the gvim window. +# Note that Gvim must use english keyboard input (choose in windows registry) +# for this to work properly as SendKeys is a piece of chunk. (i.e. it sends +# when you send a | symbol while using german key mappings) + +# pylint: skip-file + +import os +import platform +import subprocess +import unittest + +from test.constant import * +from test.vim_interface import * + +def plugin_cache_dir(): + """The directory that we check out our bundles to.""" + return os.path.join(tempfile.gettempdir(), "UltiSnips_test_vim_plugins") + +def clone_plugin(plugin): + """Clone the given plugin into our plugin directory.""" + dirname = os.path.join(plugin_cache_dir(), os.path.basename(plugin)) + print("Cloning %s -> %s" % (plugin, dirname)) + if os.path.exists(dirname): + print("Skip cloning of %s. Already there." % plugin) + return + create_directory(dirname) + subprocess.call(["git", "clone", "--recursive", + "--depth", "1", "https://github.com/%s" % plugin, dirname]) + + if plugin == "Valloric/YouCompleteMe": + ## CLUTCH: this plugin needs something extra. + subprocess.call(os.path.join(dirname, "./install.sh"), cwd=dirname) + +def setup_other_plugins(all_plugins): + """Creates /tmp/UltiSnips_test_vim_plugins and clones all plugins into this.""" + clone_plugin("tpope/vim-pathogen") + for plugin in all_plugins: + clone_plugin(plugin) + +if __name__ == '__main__': + import optparse + + def parse_args(): + p = optparse.OptionParser("%prog [OPTIONS] ") + + p.set_defaults(session="vim", interrupt=False, + verbose=False, interface="screen", retries=4, plugins=False) + + p.add_option("-v", "--verbose", dest="verbose", action="store_true", + help="print name of tests as they are executed") + p.add_option("--clone-plugins", action="store_true", + help="Only clones dependant plugins and exits the test runner.") + p.add_option("--plugins", action="store_true", + help="Run integration tests with other Vim plugins.") + p.add_option("--interface", type=str, + help="interface to vim to use on Mac and or Linux [screen|tmux].") + p.add_option("-s", "--session", dest="session", metavar="SESSION", + help="session parameters for the terminal multiplexer SESSION [%default]") + p.add_option("-i", "--interrupt", dest="interrupt", + action="store_true", + help="Stop after defining the snippet. This allows the user " \ + "to interactively test the snippet in vim. You must give " \ + "exactly one test case on the cmdline. The test will always fail." + ) + p.add_option("-r", "--retries", dest="retries", type=int, + help="How often should each test be retried before it is " + "considered failed. Works around flakyness in the terminal " + "multiplexer and race conditions in writing to the file system.") + + o, args = p.parse_args() + if o.interface not in ("screen", "tmux"): + p.error("--interface must be [screen|tmux].") + + return o, args + + def flatten_test_suite(suite): + flatten = unittest.TestSuite() + for test in suite: + if isinstance(test, unittest.TestSuite): + flatten.addTests(flatten_test_suite(test)) + else: + flatten.addTest(test) + return flatten + + def main(): + options,selected_tests = parse_args() + + all_test_suites = unittest.defaultTestLoader.discover(start_dir="test") + + vim = None + if not options.clone_plugins: + if platform.system() == "Windows": + raise RuntimeError("TODO: TestSuite is broken under windows. Volunteers wanted!.") + # vim = VimInterfaceWindows() + vim.focus() + else: + if options.interface == "screen": + vim = VimInterfaceScreen(options.session) + elif options.interface == "tmux": + vim = VimInterfaceTmux(options.session) + + all_other_plugins = set() + + tests = set() + suite = unittest.TestSuite() + + for test in flatten_test_suite(all_test_suites): + test.interrupt = options.interrupt + test.retries = options.retries + test.test_plugins = options.plugins + test.vim = vim + all_other_plugins.update(test.plugins) + + if len(selected_tests): + id = test.id().split('.')[1] + if not any([ id.startswith(t) for t in selected_tests ]): + continue + tests.add(test) + suite.addTests(tests) + + if options.plugins or options.clone_plugins: + setup_other_plugins(all_other_plugins) + if options.clone_plugins: + return + + v = 2 if options.verbose else 1 + res = unittest.TextTestRunner(verbosity=v).run(suite) + + main() + +# vim:fileencoding=utf-8:foldmarker={{{#,#}}}: diff --git a/vim/vim.symlink/bundle/ultisnips/utils/get_tm_snippets.py b/vim/vim.symlink/bundle/ultisnips/utils/get_tm_snippets.py new file mode 100755 index 0000000..3684001 --- /dev/null +++ b/vim/vim.symlink/bundle/ultisnips/utils/get_tm_snippets.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import urllib +import re +from xml.etree import ElementTree +from xml.parsers.expat import ExpatError +import htmlentitydefs +import os +import glob + + +_UNESCAPE = re.compile(ur'&\w+?;', re.UNICODE) +def unescape(s): + if s is None: + return "" + def fixup(m): + ent = m.group(0)[1:-1] + return unichr(htmlentitydefs.name2codepoint[ent]) + try: + return _UNESCAPE.sub(fixup,s) + except: + print "unescape failed: %s" % repr(s) + raise + +class UnknownVariable(Exception): + pass + +class UnsupportedVariableExpression(Exception): + pass + +def replace_vars(m): + """ Replace vars in 'content' portion. + :m: match object + :returns: string""" + var = m.group(1) + default = m.group(2) + + if not re.match(r'\w+$', var): + raise UnsupportedVariableExpression(var) + + translate_vars = { + 'TM_PHP_OPEN_TAG_WITH_ECHO': 'g:UltiSnipsOpenTagWithEcho', + 'TM_PHP_OPEN_TAG': 'g:UltiSnipsOpenTag', + 'PHPDOC_AUTHOR': 'g:snips_author', + } + # TODO: TM_SELECTED_TEXT/([\t ]*).*/$1/m + + if var in translate_vars: + newvar = translate_vars[var] + else: + # TODO: this could be autogenerated + raise UnknownVariable(var) + + return "`!v exists('%s') ? %s : '%s'`" % (newvar, newvar, default) + +def parse_content(c): + try: + data = ElementTree.fromstring(c)[0] + + rv = {} + for k,v in zip(data[::2], data[1::2]): + rv[k.text] = unescape(v.text) + + if re.search( r'\$\{\D', rv["content"] ): + rv["content"] = re.sub(r'\$\{([^\d}][^}:]*)(?::([^}]*))?\}', replace_vars, rv["content"]) + + return rv + except (ExpatError, ElementTree.ParseError) as detail: + print " Syntax Error: %s" % (detail,) + print c + return None + except UnknownVariable as detail: + print " Unknown variable: %s" % (detail,) + return None + except UnsupportedVariableExpression as detail: + print " Unsupported variable expression: %s" % (detail,) + return None + +def fetch_snippets_from_svn(name): + base_url = "http://svn.textmate.org/trunk/Bundles/" + name + ".tmbundle/" + snippet_idx = base_url + "Snippets/" + + idx_list = urllib.urlopen(snippet_idx).read() + + + rv = [] + for link in re.findall("
  • (.*?)
  • ", idx_list): + m = re.match(r'(.*)', link) + link, name = m.groups() + if name == "..": + continue + + name = unescape(name.rsplit('.', 1)[0]) # remove Extension + print "Fetching data for Snippet '%s'" % name + content = urllib.urlopen(snippet_idx + link).read() + + cont = parse_content(content) + if cont: + rv.append((name, cont)) + + return rv + +def fetch_snippets_from_dir(path): + """ Fetch snippets from a given path""" + + rv = [] + for filename in glob.glob(os.path.join(path, '*.tmSnippet')): + print "Reading file %s" % filename + f = open(filename) + content = f.read() + + cont = parse_content(content) + if cont: + name = os.path.splitext(os.path.basename(filename))[0] + rv.append((name, cont)) + return rv + +def write_snippets(snip_descr, f): + + for name, d in snip_descr: + if "tabTrigger" not in d: + continue + + if "content" not in d or d["content"] is None: + print "SKIP: %s (no content)" % (d,) + continue + + f.write('snippet %s "%s"\n' % (d["tabTrigger"], name)) + f.write(d["content"].encode("utf-8") + "\n") + f.write("endsnippet\n\n") + + + +if __name__ == '__main__': + import sys + + bundle = sys.argv[1] + + if os.path.isdir(bundle): + name = sys.argv[2] + rv = fetch_snippets_from_dir(bundle) + else: + rv = fetch_snippets_from_svn(bundle) + name = bundle.lower() + + write_snippets(rv, open("tm_" + name + ".snippets","w")) +