| Package: regexplain | Package: regexplain | ||||
| Title: Rstudio addin to help you with your regexes (in progress) | Title: Rstudio addin to help you with your regexes (in progress) | ||||
| Version: 0.0.1.9000 | |||||
| Version: 0.1.0 | |||||
| Date: 2018-03-07 | Date: 2018-03-07 | ||||
| Authors@R: person("Garrick", "Aden-Buie", email = "g.adenbuie@gmail.com", role = c("aut", "cre")) | |||||
| Authors@R: c( | |||||
| person("Garrick", "Aden-Buie", email = "g.adenbuie@gmail.com", role = c("aut", "cre")), | |||||
| person("Winston", "Chang", role = c("ctb"), comment = "Author of textInput and textAreaInput fragments from shiny"), | |||||
| person(family = "RStudio", role = "cph", comment = "Copyright holder of included shiny fragments") | |||||
| ) | |||||
| Description: Test and view regexes. | Description: Test and view regexes. | ||||
| Depends: | |||||
| R (>= 3.4.3), | |||||
| dplyr | |||||
| License: MIT + file LICENSE | |||||
| Depends: R (>= 3.4.3) | |||||
| License: GPL-3 | |||||
| Encoding: UTF-8 | Encoding: UTF-8 | ||||
| LazyData: true | LazyData: true | ||||
| Imports: | Imports: | ||||
| stringr, | |||||
| stringi, | |||||
| rlang, | |||||
| purrr, | purrr, | ||||
| dplyr, | |||||
| rmarkdown, | rmarkdown, | ||||
| knitr, | |||||
| utils, | utils, | ||||
| tidyr, | tidyr, | ||||
| rstudioapi | |||||
| rstudioapi, | |||||
| shiny, | |||||
| miniUI | |||||
| RoxygenNote: 6.0.1 | RoxygenNote: 6.0.1 | ||||
| URL: https://github.com/gadenbuie/regexplain | URL: https://github.com/gadenbuie/regexplain | ||||
| BugReports: https://github.com/gadenbuie/regexplain/issues | BugReports: https://github.com/gadenbuie/regexplain/issues | ||||
| Suggests: | |||||
| testthat |
| YEAR: 2018 | |||||
| COPYRIGHT HOLDER: Garrick Aden-Buie |
| # MIT License | |||||
| Copyright (c) 2018 Garrick Aden-Buie | |||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
| of this software and associated documentation files (the "Software"), to deal | |||||
| in the Software without restriction, including without limitation the rights | |||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
| copies of the Software, and to permit persons to whom the Software is | |||||
| furnished to do so, subject to the following conditions: | |||||
| The above copyright notice and this permission notice shall be included in all | |||||
| copies or substantial portions of the Software. | |||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| SOFTWARE. | |||||
| GNU General Public License | |||||
| ========================== | |||||
| _Version 3, 29 June 2007_ | |||||
| _Copyright © 2007 Free Software Foundation, Inc. <<http://fsf.org/>>_ | |||||
| Everyone is permitted to copy and distribute verbatim copies of this license | |||||
| document, but changing it is not allowed. | |||||
| ## Preamble | |||||
| The GNU General Public License is a free, copyleft license for software and other | |||||
| kinds of works. | |||||
| The licenses for most software and other practical works are designed to take away | |||||
| your freedom to share and change the works. By contrast, the GNU General Public | |||||
| License is intended to guarantee your freedom to share and change all versions of a | |||||
| program--to make sure it remains free software for all its users. We, the Free | |||||
| Software Foundation, use the GNU General Public License for most of our software; it | |||||
| applies also to any other work released this way by its authors. You can apply it to | |||||
| your programs, too. | |||||
| When we speak of free software, we are referring to freedom, not price. Our General | |||||
| Public Licenses are designed to make sure that you have the freedom to distribute | |||||
| copies of free software (and charge for them if you wish), that you receive source | |||||
| code or can get it if you want it, that you can change the software or use pieces of | |||||
| it in new free programs, and that you know you can do these things. | |||||
| To protect your rights, we need to prevent others from denying you these rights or | |||||
| asking you to surrender the rights. Therefore, you have certain responsibilities if | |||||
| you distribute copies of the software, or if you modify it: responsibilities to | |||||
| respect the freedom of others. | |||||
| For example, if you distribute copies of such a program, whether gratis or for a fee, | |||||
| you must pass on to the recipients the same freedoms that you received. You must make | |||||
| sure that they, too, receive or can get the source code. And you must show them these | |||||
| terms so they know their rights. | |||||
| Developers that use the GNU GPL protect your rights with two steps: **(1)** assert | |||||
| copyright on the software, and **(2)** offer you this License giving you legal permission | |||||
| to copy, distribute and/or modify it. | |||||
| For the developers' and authors' protection, the GPL clearly explains that there is | |||||
| no warranty for this free software. For both users' and authors' sake, the GPL | |||||
| requires that modified versions be marked as changed, so that their problems will not | |||||
| be attributed erroneously to authors of previous versions. | |||||
| Some devices are designed to deny users access to install or run modified versions of | |||||
| the software inside them, although the manufacturer can do so. This is fundamentally | |||||
| incompatible with the aim of protecting users' freedom to change the software. The | |||||
| systematic pattern of such abuse occurs in the area of products for individuals to | |||||
| use, which is precisely where it is most unacceptable. Therefore, we have designed | |||||
| this version of the GPL to prohibit the practice for those products. If such problems | |||||
| arise substantially in other domains, we stand ready to extend this provision to | |||||
| those domains in future versions of the GPL, as needed to protect the freedom of | |||||
| users. | |||||
| Finally, every program is threatened constantly by software patents. States should | |||||
| not allow patents to restrict development and use of software on general-purpose | |||||
| computers, but in those that do, we wish to avoid the special danger that patents | |||||
| applied to a free program could make it effectively proprietary. To prevent this, the | |||||
| GPL assures that patents cannot be used to render the program non-free. | |||||
| The precise terms and conditions for copying, distribution and modification follow. | |||||
| ## TERMS AND CONDITIONS | |||||
| ### 0. Definitions | |||||
| “This License” refers to version 3 of the GNU General Public License. | |||||
| “Copyright” also means copyright-like laws that apply to other kinds of | |||||
| works, such as semiconductor masks. | |||||
| “The Program” refers to any copyrightable work licensed under this | |||||
| License. Each licensee is addressed as “you”. “Licensees” and | |||||
| “recipients” may be individuals or organizations. | |||||
| To “modify” a work means to copy from or adapt all or part of the work in | |||||
| a fashion requiring copyright permission, other than the making of an exact copy. The | |||||
| resulting work is called a “modified version” of the earlier work or a | |||||
| work “based on” the earlier work. | |||||
| A “covered work” means either the unmodified Program or a work based on | |||||
| the Program. | |||||
| To “propagate” a work means to do anything with it that, without | |||||
| permission, would make you directly or secondarily liable for infringement under | |||||
| applicable copyright law, except executing it on a computer or modifying a private | |||||
| copy. Propagation includes copying, distribution (with or without modification), | |||||
| making available to the public, and in some countries other activities as well. | |||||
| To “convey” a work means any kind of propagation that enables other | |||||
| parties to make or receive copies. Mere interaction with a user through a computer | |||||
| network, with no transfer of a copy, is not conveying. | |||||
| An interactive user interface displays “Appropriate Legal Notices” to the | |||||
| extent that it includes a convenient and prominently visible feature that **(1)** | |||||
| displays an appropriate copyright notice, and **(2)** tells the user that there is no | |||||
| warranty for the work (except to the extent that warranties are provided), that | |||||
| licensees may convey the work under this License, and how to view a copy of this | |||||
| License. If the interface presents a list of user commands or options, such as a | |||||
| menu, a prominent item in the list meets this criterion. | |||||
| ### 1. Source Code | |||||
| The “source code” for a work means the preferred form of the work for | |||||
| making modifications to it. “Object code” means any non-source form of a | |||||
| work. | |||||
| A “Standard Interface” means an interface that either is an official | |||||
| standard defined by a recognized standards body, or, in the case of interfaces | |||||
| specified for a particular programming language, one that is widely used among | |||||
| developers working in that language. | |||||
| The “System Libraries” of an executable work include anything, other than | |||||
| the work as a whole, that **(a)** is included in the normal form of packaging a Major | |||||
| Component, but which is not part of that Major Component, and **(b)** serves only to | |||||
| enable use of the work with that Major Component, or to implement a Standard | |||||
| Interface for which an implementation is available to the public in source code form. | |||||
| A “Major Component”, in this context, means a major essential component | |||||
| (kernel, window system, and so on) of the specific operating system (if any) on which | |||||
| the executable work runs, or a compiler used to produce the work, or an object code | |||||
| interpreter used to run it. | |||||
| The “Corresponding Source” for a work in object code form means all the | |||||
| source code needed to generate, install, and (for an executable work) run the object | |||||
| code and to modify the work, including scripts to control those activities. However, | |||||
| it does not include the work's System Libraries, or general-purpose tools or | |||||
| generally available free programs which are used unmodified in performing those | |||||
| activities but which are not part of the work. For example, Corresponding Source | |||||
| includes interface definition files associated with source files for the work, and | |||||
| the source code for shared libraries and dynamically linked subprograms that the work | |||||
| is specifically designed to require, such as by intimate data communication or | |||||
| control flow between those subprograms and other parts of the work. | |||||
| The Corresponding Source need not include anything that users can regenerate | |||||
| automatically from other parts of the Corresponding Source. | |||||
| The Corresponding Source for a work in source code form is that same work. | |||||
| ### 2. Basic Permissions | |||||
| All rights granted under this License are granted for the term of copyright on the | |||||
| Program, and are irrevocable provided the stated conditions are met. This License | |||||
| explicitly affirms your unlimited permission to run the unmodified Program. The | |||||
| output from running a covered work is covered by this License only if the output, | |||||
| given its content, constitutes a covered work. This License acknowledges your rights | |||||
| of fair use or other equivalent, as provided by copyright law. | |||||
| You may make, run and propagate covered works that you do not convey, without | |||||
| conditions so long as your license otherwise remains in force. You may convey covered | |||||
| works to others for the sole purpose of having them make modifications exclusively | |||||
| for you, or provide you with facilities for running those works, provided that you | |||||
| comply with the terms of this License in conveying all material for which you do not | |||||
| control copyright. Those thus making or running the covered works for you must do so | |||||
| exclusively on your behalf, under your direction and control, on terms that prohibit | |||||
| them from making any copies of your copyrighted material outside their relationship | |||||
| with you. | |||||
| Conveying under any other circumstances is permitted solely under the conditions | |||||
| stated below. Sublicensing is not allowed; section 10 makes it unnecessary. | |||||
| ### 3. Protecting Users' Legal Rights From Anti-Circumvention Law | |||||
| No covered work shall be deemed part of an effective technological measure under any | |||||
| applicable law fulfilling obligations under article 11 of the WIPO copyright treaty | |||||
| adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention | |||||
| of such measures. | |||||
| When you convey a covered work, you waive any legal power to forbid circumvention of | |||||
| technological measures to the extent such circumvention is effected by exercising | |||||
| rights under this License with respect to the covered work, and you disclaim any | |||||
| intention to limit operation or modification of the work as a means of enforcing, | |||||
| against the work's users, your or third parties' legal rights to forbid circumvention | |||||
| of technological measures. | |||||
| ### 4. Conveying Verbatim Copies | |||||
| You may convey verbatim copies of the Program's source code as you receive it, in any | |||||
| medium, provided that you conspicuously and appropriately publish on each copy an | |||||
| appropriate copyright notice; keep intact all notices stating that this License and | |||||
| any non-permissive terms added in accord with section 7 apply to the code; keep | |||||
| intact all notices of the absence of any warranty; and give all recipients a copy of | |||||
| this License along with the Program. | |||||
| You may charge any price or no price for each copy that you convey, and you may offer | |||||
| support or warranty protection for a fee. | |||||
| ### 5. Conveying Modified Source Versions | |||||
| You may convey a work based on the Program, or the modifications to produce it from | |||||
| the Program, in the form of source code under the terms of section 4, provided that | |||||
| you also meet all of these conditions: | |||||
| * **a)** The work must carry prominent notices stating that you modified it, and giving a | |||||
| relevant date. | |||||
| * **b)** The work must carry prominent notices stating that it is released under this | |||||
| License and any conditions added under section 7. This requirement modifies the | |||||
| requirement in section 4 to “keep intact all notices”. | |||||
| * **c)** You must license the entire work, as a whole, under this License to anyone who | |||||
| comes into possession of a copy. This License will therefore apply, along with any | |||||
| applicable section 7 additional terms, to the whole of the work, and all its parts, | |||||
| regardless of how they are packaged. This License gives no permission to license the | |||||
| work in any other way, but it does not invalidate such permission if you have | |||||
| separately received it. | |||||
| * **d)** If the work has interactive user interfaces, each must display Appropriate Legal | |||||
| Notices; however, if the Program has interactive interfaces that do not display | |||||
| Appropriate Legal Notices, your work need not make them do so. | |||||
| A compilation of a covered work with other separate and independent works, which are | |||||
| not by their nature extensions of the covered work, and which are not combined with | |||||
| it such as to form a larger program, in or on a volume of a storage or distribution | |||||
| medium, is called an “aggregate” if the compilation and its resulting | |||||
| copyright are not used to limit the access or legal rights of the compilation's users | |||||
| beyond what the individual works permit. Inclusion of a covered work in an aggregate | |||||
| does not cause this License to apply to the other parts of the aggregate. | |||||
| ### 6. Conveying Non-Source Forms | |||||
| You may convey a covered work in object code form under the terms of sections 4 and | |||||
| 5, provided that you also convey the machine-readable Corresponding Source under the | |||||
| terms of this License, in one of these ways: | |||||
| * **a)** Convey the object code in, or embodied in, a physical product (including a | |||||
| physical distribution medium), accompanied by the Corresponding Source fixed on a | |||||
| durable physical medium customarily used for software interchange. | |||||
| * **b)** Convey the object code in, or embodied in, a physical product (including a | |||||
| physical distribution medium), accompanied by a written offer, valid for at least | |||||
| three years and valid for as long as you offer spare parts or customer support for | |||||
| that product model, to give anyone who possesses the object code either **(1)** a copy of | |||||
| the Corresponding Source for all the software in the product that is covered by this | |||||
| License, on a durable physical medium customarily used for software interchange, for | |||||
| a price no more than your reasonable cost of physically performing this conveying of | |||||
| source, or **(2)** access to copy the Corresponding Source from a network server at no | |||||
| charge. | |||||
| * **c)** Convey individual copies of the object code with a copy of the written offer to | |||||
| provide the Corresponding Source. This alternative is allowed only occasionally and | |||||
| noncommercially, and only if you received the object code with such an offer, in | |||||
| accord with subsection 6b. | |||||
| * **d)** Convey the object code by offering access from a designated place (gratis or for | |||||
| a charge), and offer equivalent access to the Corresponding Source in the same way | |||||
| through the same place at no further charge. You need not require recipients to copy | |||||
| the Corresponding Source along with the object code. If the place to copy the object | |||||
| code is a network server, the Corresponding Source may be on a different server | |||||
| (operated by you or a third party) that supports equivalent copying facilities, | |||||
| provided you maintain clear directions next to the object code saying where to find | |||||
| the Corresponding Source. Regardless of what server hosts the Corresponding Source, | |||||
| you remain obligated to ensure that it is available for as long as needed to satisfy | |||||
| these requirements. | |||||
| * **e)** Convey the object code using peer-to-peer transmission, provided you inform | |||||
| other peers where the object code and Corresponding Source of the work are being | |||||
| offered to the general public at no charge under subsection 6d. | |||||
| A separable portion of the object code, whose source code is excluded from the | |||||
| Corresponding Source as a System Library, need not be included in conveying the | |||||
| object code work. | |||||
| A “User Product” is either **(1)** a “consumer product”, which | |||||
| means any tangible personal property which is normally used for personal, family, or | |||||
| household purposes, or **(2)** anything designed or sold for incorporation into a | |||||
| dwelling. In determining whether a product is a consumer product, doubtful cases | |||||
| shall be resolved in favor of coverage. For a particular product received by a | |||||
| particular user, “normally used” refers to a typical or common use of | |||||
| that class of product, regardless of the status of the particular user or of the way | |||||
| in which the particular user actually uses, or expects or is expected to use, the | |||||
| product. A product is a consumer product regardless of whether the product has | |||||
| substantial commercial, industrial or non-consumer uses, unless such uses represent | |||||
| the only significant mode of use of the product. | |||||
| “Installation Information” for a User Product means any methods, | |||||
| procedures, authorization keys, or other information required to install and execute | |||||
| modified versions of a covered work in that User Product from a modified version of | |||||
| its Corresponding Source. The information must suffice to ensure that the continued | |||||
| functioning of the modified object code is in no case prevented or interfered with | |||||
| solely because modification has been made. | |||||
| If you convey an object code work under this section in, or with, or specifically for | |||||
| use in, a User Product, and the conveying occurs as part of a transaction in which | |||||
| the right of possession and use of the User Product is transferred to the recipient | |||||
| in perpetuity or for a fixed term (regardless of how the transaction is | |||||
| characterized), the Corresponding Source conveyed under this section must be | |||||
| accompanied by the Installation Information. But this requirement does not apply if | |||||
| neither you nor any third party retains the ability to install modified object code | |||||
| on the User Product (for example, the work has been installed in ROM). | |||||
| The requirement to provide Installation Information does not include a requirement to | |||||
| continue to provide support service, warranty, or updates for a work that has been | |||||
| modified or installed by the recipient, or for the User Product in which it has been | |||||
| modified or installed. Access to a network may be denied when the modification itself | |||||
| materially and adversely affects the operation of the network or violates the rules | |||||
| and protocols for communication across the network. | |||||
| Corresponding Source conveyed, and Installation Information provided, in accord with | |||||
| this section must be in a format that is publicly documented (and with an | |||||
| implementation available to the public in source code form), and must require no | |||||
| special password or key for unpacking, reading or copying. | |||||
| ### 7. Additional Terms | |||||
| “Additional permissions” are terms that supplement the terms of this | |||||
| License by making exceptions from one or more of its conditions. Additional | |||||
| permissions that are applicable to the entire Program shall be treated as though they | |||||
| were included in this License, to the extent that they are valid under applicable | |||||
| law. If additional permissions apply only to part of the Program, that part may be | |||||
| used separately under those permissions, but the entire Program remains governed by | |||||
| this License without regard to the additional permissions. | |||||
| When you convey a copy of a covered work, you may at your option remove any | |||||
| additional permissions from that copy, or from any part of it. (Additional | |||||
| permissions may be written to require their own removal in certain cases when you | |||||
| modify the work.) You may place additional permissions on material, added by you to a | |||||
| covered work, for which you have or can give appropriate copyright permission. | |||||
| Notwithstanding any other provision of this License, for material you add to a | |||||
| covered work, you may (if authorized by the copyright holders of that material) | |||||
| supplement the terms of this License with terms: | |||||
| * **a)** Disclaiming warranty or limiting liability differently from the terms of | |||||
| sections 15 and 16 of this License; or | |||||
| * **b)** Requiring preservation of specified reasonable legal notices or author | |||||
| attributions in that material or in the Appropriate Legal Notices displayed by works | |||||
| containing it; or | |||||
| * **c)** Prohibiting misrepresentation of the origin of that material, or requiring that | |||||
| modified versions of such material be marked in reasonable ways as different from the | |||||
| original version; or | |||||
| * **d)** Limiting the use for publicity purposes of names of licensors or authors of the | |||||
| material; or | |||||
| * **e)** Declining to grant rights under trademark law for use of some trade names, | |||||
| trademarks, or service marks; or | |||||
| * **f)** Requiring indemnification of licensors and authors of that material by anyone | |||||
| who conveys the material (or modified versions of it) with contractual assumptions of | |||||
| liability to the recipient, for any liability that these contractual assumptions | |||||
| directly impose on those licensors and authors. | |||||
| All other non-permissive additional terms are considered “further | |||||
| restrictions” within the meaning of section 10. If the Program as you received | |||||
| it, or any part of it, contains a notice stating that it is governed by this License | |||||
| along with a term that is a further restriction, you may remove that term. If a | |||||
| license document contains a further restriction but permits relicensing or conveying | |||||
| under this License, you may add to a covered work material governed by the terms of | |||||
| that license document, provided that the further restriction does not survive such | |||||
| relicensing or conveying. | |||||
| If you add terms to a covered work in accord with this section, you must place, in | |||||
| the relevant source files, a statement of the additional terms that apply to those | |||||
| files, or a notice indicating where to find the applicable terms. | |||||
| Additional terms, permissive or non-permissive, may be stated in the form of a | |||||
| separately written license, or stated as exceptions; the above requirements apply | |||||
| either way. | |||||
| ### 8. Termination | |||||
| You may not propagate or modify a covered work except as expressly provided under | |||||
| this License. Any attempt otherwise to propagate or modify it is void, and will | |||||
| automatically terminate your rights under this License (including any patent licenses | |||||
| granted under the third paragraph of section 11). | |||||
| However, if you cease all violation of this License, then your license from a | |||||
| particular copyright holder is reinstated **(a)** provisionally, unless and until the | |||||
| copyright holder explicitly and finally terminates your license, and **(b)** permanently, | |||||
| if the copyright holder fails to notify you of the violation by some reasonable means | |||||
| prior to 60 days after the cessation. | |||||
| Moreover, your license from a particular copyright holder is reinstated permanently | |||||
| if the copyright holder notifies you of the violation by some reasonable means, this | |||||
| is the first time you have received notice of violation of this License (for any | |||||
| work) from that copyright holder, and you cure the violation prior to 30 days after | |||||
| your receipt of the notice. | |||||
| Termination of your rights under this section does not terminate the licenses of | |||||
| parties who have received copies or rights from you under this License. If your | |||||
| rights have been terminated and not permanently reinstated, you do not qualify to | |||||
| receive new licenses for the same material under section 10. | |||||
| ### 9. Acceptance Not Required for Having Copies | |||||
| You are not required to accept this License in order to receive or run a copy of the | |||||
| Program. Ancillary propagation of a covered work occurring solely as a consequence of | |||||
| using peer-to-peer transmission to receive a copy likewise does not require | |||||
| acceptance. However, nothing other than this License grants you permission to | |||||
| propagate or modify any covered work. These actions infringe copyright if you do not | |||||
| accept this License. Therefore, by modifying or propagating a covered work, you | |||||
| indicate your acceptance of this License to do so. | |||||
| ### 10. Automatic Licensing of Downstream Recipients | |||||
| Each time you convey a covered work, the recipient automatically receives a license | |||||
| from the original licensors, to run, modify and propagate that work, subject to this | |||||
| License. You are not responsible for enforcing compliance by third parties with this | |||||
| License. | |||||
| An “entity transaction” is a transaction transferring control of an | |||||
| organization, or substantially all assets of one, or subdividing an organization, or | |||||
| merging organizations. If propagation of a covered work results from an entity | |||||
| transaction, each party to that transaction who receives a copy of the work also | |||||
| receives whatever licenses to the work the party's predecessor in interest had or | |||||
| could give under the previous paragraph, plus a right to possession of the | |||||
| Corresponding Source of the work from the predecessor in interest, if the predecessor | |||||
| has it or can get it with reasonable efforts. | |||||
| You may not impose any further restrictions on the exercise of the rights granted or | |||||
| affirmed under this License. For example, you may not impose a license fee, royalty, | |||||
| or other charge for exercise of rights granted under this License, and you may not | |||||
| initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging | |||||
| that any patent claim is infringed by making, using, selling, offering for sale, or | |||||
| importing the Program or any portion of it. | |||||
| ### 11. Patents | |||||
| A “contributor” is a copyright holder who authorizes use under this | |||||
| License of the Program or a work on which the Program is based. The work thus | |||||
| licensed is called the contributor's “contributor version”. | |||||
| A contributor's “essential patent claims” are all patent claims owned or | |||||
| controlled by the contributor, whether already acquired or hereafter acquired, that | |||||
| would be infringed by some manner, permitted by this License, of making, using, or | |||||
| selling its contributor version, but do not include claims that would be infringed | |||||
| only as a consequence of further modification of the contributor version. For | |||||
| purposes of this definition, “control” includes the right to grant patent | |||||
| sublicenses in a manner consistent with the requirements of this License. | |||||
| Each contributor grants you a non-exclusive, worldwide, royalty-free patent license | |||||
| under the contributor's essential patent claims, to make, use, sell, offer for sale, | |||||
| import and otherwise run, modify and propagate the contents of its contributor | |||||
| version. | |||||
| In the following three paragraphs, a “patent license” is any express | |||||
| agreement or commitment, however denominated, not to enforce a patent (such as an | |||||
| express permission to practice a patent or covenant not to sue for patent | |||||
| infringement). To “grant” such a patent license to a party means to make | |||||
| such an agreement or commitment not to enforce a patent against the party. | |||||
| If you convey a covered work, knowingly relying on a patent license, and the | |||||
| Corresponding Source of the work is not available for anyone to copy, free of charge | |||||
| and under the terms of this License, through a publicly available network server or | |||||
| other readily accessible means, then you must either **(1)** cause the Corresponding | |||||
| Source to be so available, or **(2)** arrange to deprive yourself of the benefit of the | |||||
| patent license for this particular work, or **(3)** arrange, in a manner consistent with | |||||
| the requirements of this License, to extend the patent license to downstream | |||||
| recipients. “Knowingly relying” means you have actual knowledge that, but | |||||
| for the patent license, your conveying the covered work in a country, or your | |||||
| recipient's use of the covered work in a country, would infringe one or more | |||||
| identifiable patents in that country that you have reason to believe are valid. | |||||
| If, pursuant to or in connection with a single transaction or arrangement, you | |||||
| convey, or propagate by procuring conveyance of, a covered work, and grant a patent | |||||
| license to some of the parties receiving the covered work authorizing them to use, | |||||
| propagate, modify or convey a specific copy of the covered work, then the patent | |||||
| license you grant is automatically extended to all recipients of the covered work and | |||||
| works based on it. | |||||
| A patent license is “discriminatory” if it does not include within the | |||||
| scope of its coverage, prohibits the exercise of, or is conditioned on the | |||||
| non-exercise of one or more of the rights that are specifically granted under this | |||||
| License. You may not convey a covered work if you are a party to an arrangement with | |||||
| a third party that is in the business of distributing software, under which you make | |||||
| payment to the third party based on the extent of your activity of conveying the | |||||
| work, and under which the third party grants, to any of the parties who would receive | |||||
| the covered work from you, a discriminatory patent license **(a)** in connection with | |||||
| copies of the covered work conveyed by you (or copies made from those copies), or **(b)** | |||||
| primarily for and in connection with specific products or compilations that contain | |||||
| the covered work, unless you entered into that arrangement, or that patent license | |||||
| was granted, prior to 28 March 2007. | |||||
| Nothing in this License shall be construed as excluding or limiting any implied | |||||
| license or other defenses to infringement that may otherwise be available to you | |||||
| under applicable patent law. | |||||
| ### 12. No Surrender of Others' Freedom | |||||
| If conditions are imposed on you (whether by court order, agreement or otherwise) | |||||
| that contradict the conditions of this License, they do not excuse you from the | |||||
| conditions of this License. If you cannot convey a covered work so as to satisfy | |||||
| simultaneously your obligations under this License and any other pertinent | |||||
| obligations, then as a consequence you may not convey it at all. For example, if you | |||||
| agree to terms that obligate you to collect a royalty for further conveying from | |||||
| those to whom you convey the Program, the only way you could satisfy both those terms | |||||
| and this License would be to refrain entirely from conveying the Program. | |||||
| ### 13. Use with the GNU Affero General Public License | |||||
| Notwithstanding any other provision of this License, you have permission to link or | |||||
| combine any covered work with a work licensed under version 3 of the GNU Affero | |||||
| General Public License into a single combined work, and to convey the resulting work. | |||||
| The terms of this License will continue to apply to the part which is the covered | |||||
| work, but the special requirements of the GNU Affero General Public License, section | |||||
| 13, concerning interaction through a network will apply to the combination as such. | |||||
| ### 14. Revised Versions of this License | |||||
| The Free Software Foundation may publish revised and/or new versions of the GNU | |||||
| General Public License from time to time. Such new versions will be similar in spirit | |||||
| to the present version, but may differ in detail to address new problems or concerns. | |||||
| Each version is given a distinguishing version number. If the Program specifies that | |||||
| a certain numbered version of the GNU General Public License “or any later | |||||
| version” applies to it, you have the option of following the terms and | |||||
| conditions either of that numbered version or of any later version published by the | |||||
| Free Software Foundation. If the Program does not specify a version number of the GNU | |||||
| General Public License, you may choose any version ever published by the Free | |||||
| Software Foundation. | |||||
| If the Program specifies that a proxy can decide which future versions of the GNU | |||||
| General Public License can be used, that proxy's public statement of acceptance of a | |||||
| version permanently authorizes you to choose that version for the Program. | |||||
| Later license versions may give you additional or different permissions. However, no | |||||
| additional obligations are imposed on any author or copyright holder as a result of | |||||
| your choosing to follow a later version. | |||||
| ### 15. Disclaimer of Warranty | |||||
| THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | |||||
| EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |||||
| PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||||
| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE | |||||
| QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE | |||||
| DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |||||
| ### 16. Limitation of Liability | |||||
| IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY | |||||
| COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS | |||||
| PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, | |||||
| INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | |||||
| PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE | |||||
| OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE | |||||
| WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |||||
| POSSIBILITY OF SUCH DAMAGES. | |||||
| ### 17. Interpretation of Sections 15 and 16 | |||||
| If the disclaimer of warranty and limitation of liability provided above cannot be | |||||
| given local legal effect according to their terms, reviewing courts shall apply local | |||||
| law that most closely approximates an absolute waiver of all civil liability in | |||||
| connection with the Program, unless a warranty or assumption of liability accompanies | |||||
| a copy of the Program in return for a fee. | |||||
| _END OF TERMS AND CONDITIONS_ | |||||
| ## How to Apply These Terms to Your New Programs | |||||
| If you develop a new program, and you want it to be of the greatest possible use to | |||||
| the public, the best way to achieve this is to make it free software which everyone | |||||
| can redistribute and change under these terms. | |||||
| To do so, attach the following notices to the program. It is safest to attach them | |||||
| to the start of each source file to most effectively state the exclusion of warranty; | |||||
| and each file should have at least the “copyright” line and a pointer to | |||||
| where the full notice is found. | |||||
| <one line to give the program's name and a brief idea of what it does.> | |||||
| Copyright (C) 2018 Garrick Aden-Buie | |||||
| This program is free software: you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation, either version 3 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
| Also add information on how to contact you by electronic and paper mail. | |||||
| If the program does terminal interaction, make it output a short notice like this | |||||
| when it starts in an interactive mode: | |||||
| regexplain Copyright (C) 2018 Garrick Aden-Buie | |||||
| This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. | |||||
| This is free software, and you are welcome to redistribute it | |||||
| under certain conditions; type 'show c' for details. | |||||
| The hypothetical commands `show w` and `show c` should show the appropriate parts of | |||||
| the General Public License. Of course, your program's commands might be different; | |||||
| for a GUI interface, you would use an “about box”. | |||||
| You should also get your employer (if you work as a programmer) or school, if any, to | |||||
| sign a “copyright disclaimer” for the program, if necessary. For more | |||||
| information on this, and how to apply and follow the GNU GPL, see | |||||
| <<http://www.gnu.org/licenses/>>. | |||||
| The GNU General Public License does not permit incorporating your program into | |||||
| proprietary programs. If your program is a subroutine library, you may consider it | |||||
| more useful to permit linking proprietary applications with the library. If this is | |||||
| what you want to do, use the GNU Lesser General Public License instead of this | |||||
| License. But first, please read | |||||
| <<http://www.gnu.org/philosophy/why-not-lgpl.html>>. |
| # Generated by roxygen2: do not edit by hand | # Generated by roxygen2: do not edit by hand | ||||
| export(regex_gadget) | |||||
| export(regexplain_cheatsheet) | |||||
| export(run_regex) | export(run_regex) | ||||
| export(view_regex) | export(view_regex) | ||||
| import(miniUI) | |||||
| import(shiny) | |||||
| importFrom(dplyr,"%>%") | |||||
| importFrom(dplyr,filter) | |||||
| importFrom(dplyr,group_by) | |||||
| importFrom(dplyr,mutate) | |||||
| importFrom(dplyr,select) | |||||
| importFrom(dplyr,summarize) | |||||
| importFrom(rlang,.data) | |||||
| importFrom(utils,getFromNamespace) |
| #' regexplain gadget | |||||
| #' | |||||
| #' @import miniUI | |||||
| #' @import shiny | |||||
| #' @param text Text to explore in gadget (editable using interface) | |||||
| #' @param start_page Open gadget to this tab, one of `"Text"`, `"Regex"`, | |||||
| #' `"Output"`, or `"Help"` | |||||
| #' @export | |||||
| regex_gadget <- function(text = NULL, | |||||
| start_page = if (is.null(text)) "Text" else "Regex") { | |||||
| stopifnot(requireNamespace("miniUI"), requireNamespace("shiny")) | |||||
| ui <- miniPage( | |||||
| shiny::includeCSS(system.file("style.css", package = "regexplain")), | |||||
| shiny::includeCSS(system.file("gadget.css", package = "regexplain")), | |||||
| gadgetTitleBar( | |||||
| "regexplain", | |||||
| right = miniTitleBarButton("done", "Send Regex To Console", TRUE) | |||||
| ), | |||||
| miniTabstripPanel( | |||||
| selected = match.arg(start_page, c("Text", "Regex", "Output", "Help")), | |||||
| miniTabPanel( | |||||
| "Text", icon = icon('file-text-o'), | |||||
| miniContentPanel( | |||||
| fillCol( | |||||
| textAreaInputAlt('text', | |||||
| label = "Text to search or parse", | |||||
| value = paste(text, collapse = "\n"), | |||||
| resize = "both", | |||||
| width = "100%", | |||||
| height="90%", | |||||
| placeholder = "Paste, enter, or edit your sample text here.") | |||||
| ) | |||||
| ) | |||||
| ), | |||||
| miniTabPanel( | |||||
| "Regex", icon = icon('terminal'), | |||||
| miniContentPanel( | |||||
| fillCol( | |||||
| flex = c(1, 3), | |||||
| fillCol( | |||||
| flex = c(1, 1), | |||||
| textInputCode('pattern', 'Regex', width = "100%", | |||||
| placeholder = "Enter regex, single \\ okay"), | |||||
| checkboxGroupInput( | |||||
| 'regex_options', | |||||
| label = "", | |||||
| inline = TRUE, | |||||
| width = "90%", | |||||
| choices = c("Break Lines" = "text_break_lines", | |||||
| "Ignore Case" = "ignore.case", | |||||
| "Perl Style" = "perl", | |||||
| "Fixed" = "fixed", | |||||
| "Use Bytes" = "useBytes" | |||||
| # , "Invert" = "invert" | |||||
| ), | |||||
| selected = c('text_break_lines') | |||||
| ) | |||||
| ), | |||||
| tags$div( | |||||
| class = "gadget-result", | |||||
| style = "overflow-y: scroll; height: 100%;", | |||||
| htmlOutput('result') | |||||
| ) | |||||
| ) | |||||
| ) | |||||
| ), | |||||
| miniTabPanel( | |||||
| "Output", icon = icon("table"), | |||||
| miniContentPanel( | |||||
| fillCol( | |||||
| flex = c(1, 3), | |||||
| inputPanel( | |||||
| width = "100%;", | |||||
| selectInput('regexFn', label = 'Apply Function', | |||||
| choices = regexFn_choices) | |||||
| ), | |||||
| # verbatimTextOutput('output_result', placeholder = TRUE) | |||||
| tags$pre( | |||||
| id = "output_result", | |||||
| class = "shiny-text-output", | |||||
| style = "overflow-y: scroll; height: 100%;" | |||||
| ) | |||||
| ) | |||||
| ) | |||||
| ), | |||||
| miniTabPanel( | |||||
| "Help", icon = icon("support"), | |||||
| help_ui("help") | |||||
| ) | |||||
| ) | |||||
| ) | |||||
| server <- function(input, output, session) { | |||||
| rtext <- reactive({ | |||||
| x <- if ('text_break_lines' %in% input$regex_options) { | |||||
| strsplit(input$text, "\n")[[1]] | |||||
| } else input$text | |||||
| x | |||||
| }) | |||||
| pattern <- reactive({ | |||||
| sanitize_text_input(input$pattern) | |||||
| }) | |||||
| alert_result <- function(msg, type = "danger") { | |||||
| msg <- gsub("\n", "<br>", msg) | |||||
| msg <- gsub("\t", " ", msg) | |||||
| paste0("<pre class='alert alert-", type, "' ", | |||||
| "style='padding: 4px; margin-top: 1px; margin-bottom: 4px;'>", | |||||
| paste(msg, collapse = "<br>"), | |||||
| "</pre>") | |||||
| } | |||||
| output$result <- renderUI({ | |||||
| if (is.null(rtext())) return(NULL) | |||||
| if (pattern() == "") { | |||||
| return(toHTML(paste('<p class="results">', escape_html(rtext()), "</p>", collapse = ""))) | |||||
| } | |||||
| res <- NULL | |||||
| error_message <- NULL | |||||
| warning_message <- NULL | |||||
| tryCatch({ | |||||
| res <- paste( | |||||
| view_regex( | |||||
| rtext(), | |||||
| pattern(), | |||||
| ignore.case = 'ignore.case' %in% input$regex_options, | |||||
| perl = 'perl' %in% input$regex_options, | |||||
| fixed = 'fixed' %in% input$regex_options, | |||||
| useBytes = 'useBytes' %in% input$regex_options, | |||||
| # invert = 'invert' %in% input$regex_options, | |||||
| render = FALSE, | |||||
| escape = TRUE), | |||||
| collapse = "" | |||||
| ) | |||||
| }, | |||||
| error = function(e) { | |||||
| error_message <<- alert_result(e$message, "danger") | |||||
| }, | |||||
| warning = function(w) { | |||||
| warning_message <<- alert_result(w$message, "warning") | |||||
| }) | |||||
| if (is.null(res)) res <- toHTML( | |||||
| paste('<p class="results">', escape_html(rtext()), "</p>", collapse = "") | |||||
| ) | |||||
| toHTML(paste(error_message, warning_message, res)) | |||||
| }) | |||||
| output$output_result <- renderPrint({ | |||||
| req(input$regexFn) | |||||
| regexPkg <- get_pkg_namespace(input$regexFn) | |||||
| regexFn <- getFromNamespace(input$regexFn, regexPkg) | |||||
| x <- if (regexPkg == "base") { | |||||
| regexFn(pattern(), rtext()) | |||||
| } else if (regexPkg == "stringr") { | |||||
| regexFn(rtext(), pattern()) | |||||
| } else { | |||||
| "Um. Not sure how I got here." | |||||
| } | |||||
| print(x) | |||||
| }) | |||||
| # ---- Help Section ---- # | |||||
| help_text <- callModule(help_server, "help") | |||||
| observeEvent(input$done, { | |||||
| # browser() | |||||
| if (pattern() != "") { | |||||
| pattern <- paste0('regex <- "', escape_backslash(pattern()), '"') | |||||
| rstudioapi::sendToConsole(pattern, FALSE) | |||||
| } | |||||
| stopApp() | |||||
| }) | |||||
| observeEvent(input$cancel, { | |||||
| stopApp() | |||||
| }) | |||||
| } | |||||
| viewer <- shiny::paneViewer(700) | |||||
| runGadget(ui, server, viewer = viewer) | |||||
| } | |||||
| sanitize_text_input <- function(x) { | |||||
| if (grepl("\\u|\\x|\\N|\\a|\\o", x)) { | |||||
| try({ | |||||
| y <- stringi::stri_unescape_unicode(x) | |||||
| }, silent = TRUE) | |||||
| if (!is.na(y)) x <- y | |||||
| } | |||||
| # x <- gsub("\u201C|\u201D", '"', x) | |||||
| # x <- gsub("\u2018|\u2019", "'", x) | |||||
| x | |||||
| } | |||||
| toHTML <- function(...) { | |||||
| x <- paste(..., collapse = "") | |||||
| x <- gsub("\n", "\\\\n", x) | |||||
| x <- gsub("\t", "\\\\t", x) | |||||
| x <- gsub("\r", "\\\\r", x) | |||||
| HTML(x) | |||||
| } | |||||
| regexFn_choices <- list( | |||||
| "Choose a function" = "", | |||||
| base = c( | |||||
| "grep", | |||||
| "grepl", | |||||
| "regexpr", | |||||
| "gregexpr", | |||||
| "regexec" | |||||
| ), | |||||
| stringr = c( | |||||
| "str_detect", | |||||
| "str_locate", | |||||
| "str_locate_all", | |||||
| "str_extract", | |||||
| "str_extract_all", | |||||
| "str_match", | |||||
| "str_match_all", | |||||
| "str_split" | |||||
| ) | |||||
| ) | |||||
| get_pkg_namespace <- function(fn) { | |||||
| x <- names(purrr::keep(regexFn_choices, ~ (fn %in% .))) | |||||
| if (length(x) > 1) warning(fn, " matches multiple functions in regexFn_choices, please review.") | |||||
| x | |||||
| } | |||||
| #' Regex Cheatsheet Quick Reference | |||||
| #' | |||||
| #' @import miniUI | |||||
| #' @import shiny | |||||
| #' @export | |||||
| regexplain_cheatsheet <- function() { | |||||
| stopifnot(requireNamespace("miniUI"), requireNamespace("shiny")) | |||||
| ui <- miniPage( | |||||
| shiny::includeCSS(system.file("gadget.css", package = "regexplain")), | |||||
| gadgetTitleBar( | |||||
| "Regex Cheatsheet Quick Reference", | |||||
| right = miniTitleBarButton("done", "OK", TRUE) | |||||
| ), | |||||
| help_ui("help") | |||||
| ) | |||||
| server <- function(input, output, session) { | |||||
| help_text <- callModule(help_server, "help") | |||||
| observeEvent(input$done, { | |||||
| stopApp() | |||||
| }) | |||||
| observeEvent(input$cancel, { | |||||
| stopApp() | |||||
| }) | |||||
| } | |||||
| viewer <- shiny::paneViewer(700) | |||||
| runGadget(ui, server, viewer = viewer) | |||||
| } | |||||
| help_ui <- function(id) { | |||||
| ns <- NS(id) | |||||
| miniContentPanel( | |||||
| fillRow( | |||||
| flex = c(1, 4), | |||||
| tagList( | |||||
| tags$ul( | |||||
| id = "help-sidebar", | |||||
| tags$li("Character Classes", class = "header"), | |||||
| tags$ul( | |||||
| class = "subgroup", | |||||
| tags$li(actionLink(ns("help_cat_character_classes_regular"), "Regular")), | |||||
| tags$li(actionLink(ns("help_cat_character_classes_prebuilt"), "Pre-Built")) | |||||
| ), | |||||
| tags$li(actionLink(ns("help_cat_anchors"), "Anchors")), | |||||
| tags$li("Escaped Characters", class = "header"), | |||||
| tags$ul( | |||||
| class = "subgroup", | |||||
| tags$li(actionLink(ns("help_cat_escaped_general"), "General")), | |||||
| tags$li(actionLink(ns("help_cat_escaped_hex"), "Hex")), | |||||
| tags$li(actionLink(ns("help_cat_escaped_control"), "Control Characters")) | |||||
| ), | |||||
| tags$li(actionLink(ns("help_cat_groups"), "Groups")), | |||||
| tags$li(actionLink(ns("help_cat_quantifiers"), "Quantifiers")) | |||||
| ) | |||||
| ), | |||||
| tags$div( | |||||
| style = "width: 100%; padding-left: 10px;", | |||||
| uiOutput(ns('help_text_selected')) | |||||
| ) | |||||
| ) | |||||
| ) | |||||
| } | |||||
| #' @importFrom rlang .data | |||||
| help_server <- function(input, output, session) { | |||||
| help_text <- reactiveVal("<p>Select a category from the left sidebar.</p>") | |||||
| make_html_table <- function(x) { | |||||
| select(x, .data$regexp, .data$text) %>% | |||||
| knitr::kable( | |||||
| col.names = c("Regexp", "Text"), | |||||
| escape = FALSE, | |||||
| format = "html") | |||||
| } | |||||
| output$help_text_selected <- renderUI({ | |||||
| HTML(help_text()) | |||||
| }) | |||||
| observeEvent(input$help_cat_character_classes_regular, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "character classes", .data$group == "regular") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_character_classes_prebuilt, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "character classes", .data$group == "pre-built") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_anchors, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "anchors") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_escaped_general, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "escaped characters", .data$group == "general") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_escaped_hex, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "escaped characters", .data$group == "hex") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_escaped_control, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "escaped characters", .data$group == "control characters") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_groups, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "groups") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| observeEvent(input$help_cat_quantifiers, { | |||||
| cheatsheet %>% | |||||
| filter(.data$category == "quantifiers") %>% | |||||
| make_html_table() %>% | |||||
| help_text() | |||||
| }) | |||||
| } |
| #' regexplain_addin | |||||
| #' | |||||
| #' @keywords internal | |||||
| regexplain_addin <- function() { | |||||
| # Get the document context. | |||||
| context <- rstudioapi::getActiveDocumentContext() | |||||
| # Get context text | |||||
| ctx_text <- context$selection[[1]]$text | |||||
| # If it is one line and evaluates to something, use that | |||||
| # Otherwise treat as text | |||||
| obj <- tryCatch({ | |||||
| if (grepl("\n", ctx_text)) { | |||||
| ctx_text[1:min(length(ctx_text), 100)] | |||||
| } else { | |||||
| x <- eval(parse(text = ctx_text)) | |||||
| x <- as.character(x) | |||||
| if (length(x) == 1 && grepl("\n", x)) | |||||
| x <- strsplit(x, "\n")[[1]] | |||||
| if (length(x) > 10) { | |||||
| message(ctx_text, " gave ", length(x), " lines, limiting to first 10 unique lines.") | |||||
| x <- unique(x) | |||||
| x[1:min(length(x), 10)] | |||||
| } else x | |||||
| } | |||||
| }, | |||||
| error = function(e) {as.character(ctx_text[1:min(length(ctx_text), 100)])}) | |||||
| regex_gadget(if (length(obj) && obj != "") obj) | |||||
| } | |||||
| #' regexplain file loader | |||||
| #' | |||||
| #' @keywords internal | |||||
| regexplain_file <- function() { | |||||
| fname <- file.choose() | |||||
| x <- readLines(fname) | |||||
| if (length(x) > 100) { | |||||
| message("There were ", format(length(x), big.mark = ","), " lines in ", fname, "\nUsing only first 100.") | |||||
| x <- x[1:100] | |||||
| } | |||||
| regex_gadget(x, "Regex") | |||||
| } |
| #' Extract matched groups from regexp | |||||
| #' | |||||
| #' @param text Text to search | |||||
| #' @param pattern regexp | |||||
| #' @inheritParams base::regexec | |||||
| #' @export | #' @export | ||||
| run_regex <- function( | run_regex <- function( | ||||
| text, | text, | ||||
| useBytes = FALSE, | useBytes = FALSE, | ||||
| invert = FALSE | invert = FALSE | ||||
| ) { | ) { | ||||
| # Use regex to get matches by group, gives start index and length | |||||
| m <- regexec(pattern, text, ignore.case, perl, fixed, useBytes) | m <- regexec(pattern, text, ignore.case, perl, fixed, useBytes) | ||||
| x <- purrr::map(purrr::set_names(m, text), function(mi) list('idx' = purrr::map2(mi, attr(mi, "match.length"), ~ if(.x[1] != -1) c(.x, .x + .y - 1L)))) | |||||
| y <- purrr::map(purrr::set_names(text), ~ list(text = .)) | |||||
| z <- purrr::map(purrr::set_names(regmatches(text, m), text), ~ list(m = .)) | |||||
| x <- utils::modifyList(y, x, TRUE) | |||||
| utils::modifyList(z, x, TRUE) | |||||
| # Convert to start/end index | |||||
| x <- purrr::map(m, function(mi) { | |||||
| list( | |||||
| 'idx' = purrr::map2(mi, attr(mi, "match.length"), | |||||
| ~ if(.x[1] != -1) c(.x, .x + .y - 1L))) | |||||
| }) | |||||
| # Store text and original regexc result with same hierarchy | |||||
| y <- purrr::map(text, ~ list(text = .)) | |||||
| z <- purrr::map(regmatches(text, m), ~ list(m = .)) | |||||
| # Zip text, indexes and regexc match object lists | |||||
| purrr::map(seq_along(x), ~ list(text = y[[.]][[1]], idx = x[[.]][[1]], m = z[[.]][[1]])) | |||||
| } | } | ||||
| wrap_result <- function(x, escape = FALSE) { | wrap_result <- function(x, escape = FALSE) { | ||||
| if (is.null(x$idx[[1]])) return(x$text) | |||||
| if (is.null(x$idx[[1]])) return(if (escape) escape_html(x$text) else x$text) | |||||
| text <- x$text | text <- x$text | ||||
| idx <- x$idx | idx <- x$idx | ||||
| len_idx <- length(idx) | len_idx <- length(idx) | ||||
| end = purrr::map_int(idx, ~ .[2]) + 1 | end = purrr::map_int(idx, ~ .[2]) + 1 | ||||
| ) %>% | ) %>% | ||||
| mutate( | mutate( | ||||
| class = sprintf("group g%02d", i), | |||||
| class = sprintf("group g%02d", .data$i), | |||||
| pad = 0 | pad = 0 | ||||
| ) | ) | ||||
| for (j in seq_len(nrow(inserts))) { | for (j in seq_len(nrow(inserts))) { | ||||
| if (inserts$i[j] == 0) next | if (inserts$i[j] == 0) next | ||||
| overlap <- filter( | overlap <- filter( | ||||
| inserts[1:(j-1), ], | inserts[1:(j-1), ], | ||||
| i != 0, | |||||
| start <= !!inserts$start[j] & end >= !!inserts$end[j]) | |||||
| .data$i != 0, | |||||
| .data$start <= !!inserts$start[j] & .data$end >= !!inserts$end[j]) | |||||
| inserts[j, 'pad'] <- inserts$pad[j] + nrow(overlap) | inserts[j, 'pad'] <- inserts$pad[j] + nrow(overlap) | ||||
| } | } | ||||
| inserts <- inserts %>% | inserts <- inserts %>% | ||||
| tidyr::gather(type, loc, start:end) %>% | tidyr::gather(type, loc, start:end) %>% | ||||
| mutate( | mutate( | ||||
| class = ifelse(pad > 0, sprintf("%s pad%02d", class, pad), class), | |||||
| insert = ifelse(type == 'start', sprintf('<span class="%s">', class), "</span>") | |||||
| class = ifelse(.data$pad > 0, sprintf("%s pad%02d", .data$class, .data$pad), .data$class), | |||||
| insert = ifelse(.data$type == 'start', sprintf('<span class="%s">', .data$class), "</span>") | |||||
| ) %>% | ) %>% | ||||
| group_by(loc, type) %>% | |||||
| summarize(insert = paste(insert, collapse = '')) | |||||
| group_by(.data$loc, .data$type) %>% | |||||
| summarize(insert = paste(.data$insert, collapse = '')) | |||||
| # inserts now gives html (span open and close) to insert and loc | # inserts now gives html (span open and close) to insert and loc | ||||
| # first split text at inserts$loc locations, | # first split text at inserts$loc locations, | ||||
| x <- strsplit(pattern, r_open_parens, perl = TRUE)[[1]] | x <- strsplit(pattern, r_open_parens, perl = TRUE)[[1]] | ||||
| first <- x[1] | first <- x[1] | ||||
| x <- x[-1] | x <- x[-1] | ||||
| x <- paste0( | |||||
| '<span class="g', sprintf("%02d", seq_along(x)), '">(', | |||||
| x, | |||||
| collapse = "" | |||||
| ) | |||||
| x <- gsub("(?<![\\\\])\\)", ")</span>", x, perl = TRUE) | |||||
| if (exact) x <- gsub("\\\\", "\\\\\\\\", x) | |||||
| if (length(x)) { | |||||
| x <- paste0( | |||||
| '<span class="g', sprintf("%02d", seq_along(x)), '">(', | |||||
| x, | |||||
| collapse = "" | |||||
| ) | |||||
| x <- gsub("(?<![\\\\])\\)", ")</span>", x, perl = TRUE) | |||||
| } | |||||
| if (exact) x <- escape_backslash(x) | |||||
| paste0(first, x) | paste0(first, x) | ||||
| } | } | ||||
| } | } | ||||
| res <- run_regex(text, pattern, ...) | res <- run_regex(text, pattern, ...) | ||||
| res <- purrr::map_chr(res, wrap_result, escape = escape) | res <- purrr::map_chr(res, wrap_result, escape = escape) | ||||
| res <- paste("<p class='results'>", res, "</p>") | |||||
| res <- purrr::map_chr(res, function(resi) { | |||||
| result_pad <- "" | |||||
| if (grepl("pad\\d{2}", resi)) { | |||||
| max_pad <- max(stringr::str_extract_all(resi, "pad\\d{2}")[[1]]) | |||||
| max_pad_level <- as.integer(stringr::str_extract(max_pad, "\\d{2}")) | |||||
| if (max_pad_level - 3 > 0) { | |||||
| result_pad <- sprintf("pad%02d", max_pad_level - 3) | |||||
| } | |||||
| } | |||||
| paste("<p class='results", result_pad, "'>", resi, "</p>") | |||||
| }) | |||||
| res <- paste(res, collapse = "") | |||||
| if (!nchar(pattern)) res <- paste("<p class='results'>", text, "</p>") | |||||
| if (knitr) return(knitr::asis_output(res)) | if (knitr) return(knitr::asis_output(res)) | ||||
| if (!render) return(res) | if (!render) return(res) | ||||
| head <- c( | head <- c( |
| # ---- Modified Shiny Inputs ---- | |||||
| # The shiny package as a whole is distributed under GPL-3 | |||||
| # (GNU GENERAL PUBLIC LICENSE version 3). | |||||
| # See https://github.com/rstudio/shiny/blob/master/LICENSE | |||||
| #' Modified Text Area Input | |||||
| #' | |||||
| #' Standard [shiny::textAreaInput()] with additional `is_code` parameter, added | |||||
| #' code font style for the input text and with `autocomplete`, `autocorrect`, | |||||
| #' `autocapitalize` and `spellcheck` set to `off` or `false`. | |||||
| #' | |||||
| #' @inheritParams shiny::textAreaInput | |||||
| #' @param is_code Should the text input be considered verbatim code input? | |||||
| textAreaInputAlt <- function(inputId, label, value = "", width = NULL, height = NULL, | |||||
| cols = NULL, rows = NULL, placeholder = NULL, resize = NULL, | |||||
| is_code = TRUE) { | |||||
| `%AND%` <- getFromNamespace("%AND%", "shiny") | |||||
| value <- shiny::restoreInput(id = inputId, default = value) | |||||
| if (!is.null(resize)) { | |||||
| resize <- match.arg(resize, c("both", "none", "vertical", "horizontal")) | |||||
| } | |||||
| style <- paste( | |||||
| if (!is.null(width)) paste0("width: ", shiny::validateCssUnit(width), ";"), | |||||
| if (!is.null(height)) paste0("height: ", shiny::validateCssUnit(height), ";"), | |||||
| if (!is.null(resize)) paste0("resize: ", resize, ";"), | |||||
| if (is_code) 'font-family: "Monaco", "Inconsolata", monospace;' | |||||
| ) | |||||
| parent_style <- paste( | |||||
| if (!is.null(width) && grepl("%", width)) paste0("width: ", width, ";"), | |||||
| if (!is.null(height) && grepl("%", height)) paste0("height: ", height, ";") | |||||
| ) | |||||
| # Workaround for tag attribute=character(0) bug: | |||||
| # https://github.com/rstudio/htmltools/issues/65 | |||||
| if (length(style) == 0) style <- NULL | |||||
| shiny::div(class = "form-group shiny-input-container", | |||||
| label %AND% shiny::tags$label(label, `for` = inputId), | |||||
| style = if (!parent_style %in% c(" ", "", " ")) parent_style, | |||||
| shiny::tags$textarea( | |||||
| id = inputId, | |||||
| class = "form-control", | |||||
| placeholder = placeholder, | |||||
| style = style, | |||||
| rows = rows, | |||||
| cols = cols, | |||||
| autocomplete = "off", | |||||
| autocorrect = "off", | |||||
| autocapitalize = "off", | |||||
| spellcheck = "false", | |||||
| value | |||||
| ) | |||||
| ) | |||||
| } | |||||
| #' Modified Text Input | |||||
| #' | |||||
| #' Standard [shiny::textInput()] with additional `width` parameter, added code | |||||
| #' font style for the input text and with `autocomplete`, `autocorrect`, | |||||
| #' `autocapitalize` and `spellcheck` set to `off` or `false`. | |||||
| #' | |||||
| #' @inheritParams shiny::textInput | |||||
| #' @param width Width of `shiny-input-container` div. | |||||
| textInputCode <- function(inputId, label, value = "", width = NULL, | |||||
| placeholder = NULL) { | |||||
| `%AND%` <- getFromNamespace("%AND%", "shiny") | |||||
| value <- shiny::restoreInput(id = inputId, default = value) | |||||
| shiny::div(class = "form-group shiny-input-container", | |||||
| style = if (!is.null(width)) paste0("width: ", shiny::validateCssUnit(width), ";"), | |||||
| label %AND% shiny::tags$label(label, `for` = inputId), | |||||
| shiny::tags$input(id = inputId, type="text", class="form-control", value=value, | |||||
| style = 'font-family: "Monaco", "Inconsolata", monospace;', | |||||
| autocomplete = "off", autocorrect = "off", | |||||
| autocapitalize = "off", spellcheck = "false", | |||||
| placeholder = placeholder) | |||||
| ) | |||||
| } |
| #' @importFrom dplyr "%>%" mutate filter group_by summarize select | |||||
| #' @importFrom utils getFromNamespace | |||||
| NULL | |||||
| escape_html <- function(x) { | escape_html <- function(x) { | ||||
| x = gsub("&", "&", x) | x = gsub("&", "&", x) | ||||
| x = gsub("<", "<", x) | x = gsub("<", "<", x) | ||||
| x = gsub(">", ">", x) | x = gsub(">", ">", x) | ||||
| x = gsub("\"", """, x) | x = gsub("\"", """, x) | ||||
| x = gsub(" ", " ", x) | |||||
| x | x | ||||
| } | } | ||||
| escape_backslash <- function(x) { | |||||
| gsub("\\\\", "\\\\\\\\", x) | |||||
| } |
| title: "regexplain" | title: "regexplain" | ||||
| output: github_document | output: github_document | ||||
| --- | --- | ||||
| [](commits/master) | |||||
|  | |||||
| [](http://www.repostatus.org/#active) | |||||
| [](https://cran.r-project.org/package=regexplain) | |||||
| [)`-yellowgreen.svg)](/commits/master) | |||||
| ```{r setup, include=FALSE} | ```{r setup, include=FALSE} | ||||
| knitr::opts_chunk$set(echo = TRUE) | knitr::opts_chunk$set(echo = TRUE) | ||||
| library(regexplain) | library(regexplain) | ||||
| ``` | ``` | ||||
| <!-- Links --> | <!-- Links --> | ||||
| [regexr]: https://regexr.com/ | [regexr]: https://regexr.com/ | ||||
| ## WORK IN PROGRESS!! | |||||
| regexplain is going to be an RStudio addin that helps you interactively build up your regex. | |||||
| regexplain is an RStudio addin that helps you interactively build up your regex expressions. | |||||
| Inspired by [RegExr][regexr] and `stringr::str_view`. | Inspired by [RegExr][regexr] and `stringr::str_view`. | ||||
| ## Done (ish) | |||||
| ## Installation | |||||
| Installation is easy with `devtools`: | |||||
| ```r | |||||
| devtools::install_github("gadenbuie/regexplain") | |||||
| ``` | |||||
| ## Status | |||||
| Mostly working, but there [may be issues or future changes](#issues). | |||||
| I would love your help testing this, feel free to send me your feedback on Twitter at [@grrrck](https://twitter.com/grrrck) or through the [issue tracker](https://github.com/gadenbuie/regexplain). | |||||
| ## RStudio Addin | |||||
|  | |||||
| The main feature of this package is the RStudio Addin **Regexplain Selection**. | |||||
| Just select the text or object containing text (such as the variable name of a vector or a data.frame column) and run **Regexplain Selection** from the RStudio Addins dropdown. | |||||
| <img src="docs/rstudio-addin-list.png" width = "250px;" alt="regexplain in the Rstudio Addins dropdown"> | |||||
| The addin will open an interface with 4 panes where you can | |||||
| You can use `view_regex()` for a `stringr::str_view()` replacement that includes groups. | |||||
| - edit the **text** you've imported | |||||
| - build up a **regex** expression and interactively see it applied to your text | |||||
| - test the **output** of common string matching functions from `base` and `stringr` | |||||
| - and refer to a **help**ful cheatsheet | |||||
|  | |||||
| When you're done, click on the **Send Regex to Console** to send your regex expression to... the console! | |||||
| ```r | |||||
| > regex <- "(is|were|was) ([[:alpha:]]+) ([[:alpha:]]+)" | |||||
| ``` | |||||
| ### Additional Addins | |||||
| There are two more addins. | |||||
| **Regexplain File** lets you import the text lines from a file containing the text you want to process with regular expressions. | |||||
| **Regexplain Cheatsheet** opens the help page in the Viewer pane without blocking your current R session. | |||||
| ## View regex results without the interactivity | |||||
| regexplain also provides the function `view_regex()` that you can use as a `stringr::str_view()` replacement. | |||||
| In addition to highlighting matched portions of the text, `view_regex()` also colorizes groups and attemps to colorize the regex expression itself as well. | |||||
| ```r | ```r | ||||
| text <- c("breakfast=eggs;lunch=pizza", | text <- c("breakfast=eggs;lunch=pizza", | ||||
|  |  | ||||
| ## Planned (ish) | |||||
| ## Known Issues and Future Work {#issues} | |||||
| Regular expressions are nothing if not a collection of corner cases. | |||||
| Trying to pass regular expressions through Shiny and HTML inputs is a bit of a labrynth. | |||||
| For now, assume any issues or oddities you experience with this addin are entirely my fault and have nothing to do with the fine packages this addin is built on. | |||||
| If you do find an issue, [please file an issue](https://github.com/gadenbuie/regexplain). | |||||
| #### Things I know are wonky | |||||
| - Things get weird when regular text is surrounded by capture groups, i.e. `"(\w+) not grouped (\w+)"`. | |||||
| - `view_regex()` colorizes non-capture groups. I forgot about them when building that feature, I'll get back to it. | |||||
| #### Notes | |||||
| 1. An Rstudio addin gadget that allows you to interactively enter the regex and see the results. | |||||
| Like the above example, where the regex field is a text input. | |||||
| - I've set up this app so that most escape sequences don't need to be escaped. | |||||
| For example, you can enter `\w`, whereas in R this would need to be stored as | |||||
| `"\\w"`. The regex returned by the gadget will include the double backslash. | |||||
| In these cases the text input is not escaped by Shiny. | |||||
| Unicode and hex escape characters also do not need to be escaped, thanks to | |||||
| `stringi::stri_unescape_unicode()`. Here, `"\u"` *is* escaped by Shiny so I | |||||
| had to make sure they are unescaped. The list of escaped characters that get | |||||
| unescaped is `"\\u|\\x|\\N|\\a|\\o"`, please let me know if you find any | |||||
| others that should be on this list. | |||||
| 2. Import data from your environment, like a character vector, file, or data.frame column when opening the gadget. | |||||
| #### Planned improvements | |||||
| 3. Help tab in the gadget, pulling from `?regex` but with some navigation. | |||||
| - I may add `stringi` functions to the list of available functions in the **Output** tab. | |||||
| 4. Tab to interactively explore output of varying regex-applying functions. In other words, see what `stringr::str_locate_all` or `stringr::str_match_all` or `grep` or `grepl` return when applying the regex to your text. | |||||
| - I would like to add the regex/function options for the functions in the **Output** tab, similar to the options present in the **Regex** tab. |
| regexplain | regexplain | ||||
| ================ | ================ | ||||
| <!-- Links --> | |||||
| [](commits/master) | |||||
|  | |||||
| [](http://www.repostatus.org/#active) | |||||
| [](https://cran.r-project.org/package=regexplain) | |||||
| [](/commits/master) | |||||
| ## WORK IN PROGRESS\!\! | |||||
| <!-- Links --> | |||||
| regexplain is going to be an RStudio addin that helps you interactively | |||||
| build up your regex. Inspired by [RegExr](https://regexr.com/) and | |||||
| regexplain is an RStudio addin that helps you interactively build up | |||||
| your regex expressions. Inspired by [RegExr](https://regexr.com/) and | |||||
| `stringr::str_view`. | `stringr::str_view`. | ||||
| ## Done (ish) | |||||
| ## Installation | |||||
| Installation is easy with `devtools`: | |||||
| ``` r | |||||
| devtools::install_github("gadenbuie/regexplain") | |||||
| ``` | |||||
| ## Status | |||||
| Mostly working, but there [may be issues or future changes](#issues). | |||||
| I would love your help testing this, feel free to send me your feedback | |||||
| on Twitter at [@grrrck](https://twitter.com/grrrck) or through the | |||||
| [issue tracker](https://github.com/gadenbuie/regexplain). | |||||
| ## RStudio Addin | |||||
|  | |||||
| The main feature of this package is the RStudio Addin **Regexplain | |||||
| Selection**. Just select the text or object containing text (such as the | |||||
| variable name of a vector or a data.frame column) and run **Regexplain | |||||
| Selection** from the RStudio Addins | |||||
| dropdown. | |||||
| <img src="docs/rstudio-addin-list.png" width = "250px;" alt="regexplain in the Rstudio Addins dropdown"> | |||||
| The addin will open an interface with 4 panes where you can | |||||
| You can use `view_regex()` for a `stringr::str_view()` replacement that | |||||
| includes groups. | |||||
| - edit the **text** you’ve imported | |||||
| - build up a **regex** expression and interactively see it applied to | |||||
| your text | |||||
| - test the **output** of common string matching functions from `base` | |||||
| and `stringr` | |||||
| - and refer to a **help**ful cheatsheet | |||||
|  | |||||
| When you’re done, click on the **Send Regex to Console** to send your | |||||
| regex expression to… the console\! | |||||
| ``` r | |||||
| > regex <- "(is|were|was) ([[:alpha:]]+) ([[:alpha:]]+)" | |||||
| ``` | |||||
| ### Additional Addins | |||||
| There are two more addins. **Regexplain File** lets you import the text | |||||
| lines from a file containing the text you want to process with regular | |||||
| expressions. **Regexplain Cheatsheet** opens the help page in the Viewer | |||||
| pane without blocking your current R session. | |||||
| ## View regex results without the interactivity | |||||
| regexplain also provides the function `view_regex()` that you can use as | |||||
| a `stringr::str_view()` replacement. In addition to highlighting matched | |||||
| portions of the text, `view_regex()` also colorizes groups and attemps | |||||
| to colorize the regex expression itself as well. | |||||
| ``` r | ``` r | ||||
| text <- c("breakfast=eggs;lunch=pizza", | text <- c("breakfast=eggs;lunch=pizza", | ||||
|  |  | ||||
| ## Planned (ish) | |||||
| ## Known Issues and Future Work | |||||
| Regular expressions are nothing if not a collection of corner cases. | |||||
| Trying to pass regular expressions through Shiny and HTML inputs is a | |||||
| bit of a labrynth. For now, assume any issues or oddities you experience | |||||
| with this addin are entirely my fault and have nothing to do with the | |||||
| fine packages this addin is built on. If you do find an issue, [please | |||||
| file an issue](https://github.com/gadenbuie/regexplain). | |||||
| #### Things I know are wonky | |||||
| - Things get weird when regular text is surrounded by capture groups, | |||||
| i.e. `"(\w+) not grouped (\w+)"`. | |||||
| - `view_regex()` colorizes non-capture groups. I forgot about them | |||||
| when building that feature, I’ll get back to it. | |||||
| #### Notes | |||||
| 1. An Rstudio addin gadget that allows you to interactively enter the | |||||
| regex and see the results. Like the above example, where the regex | |||||
| field is a text input. | |||||
| - I’ve set up this app so that most escape sequences don’t need to be | |||||
| escaped. For example, you can enter `\w`, whereas in R this would | |||||
| need to be stored as `"\\w"`. The regex returned by the gadget will | |||||
| include the double backslash. In these cases the text input is not | |||||
| escaped by Shiny. | |||||
| Unicode and hex escape characters also do not need to be escaped, | |||||
| thanks to `stringi::stri_unescape_unicode()`. Here, `"\u"` *is* | |||||
| escaped by Shiny so I had to make sure they are unescaped. The list | |||||
| of escaped characters that get unescaped is `"\\u|\\x|\\N|\\a|\\o"`, | |||||
| please let me know if you find any others that should be on this | |||||
| list. | |||||
| 2. Import data from your environment, like a character vector, file, or | |||||
| data.frame column when opening the gadget. | |||||
| #### Planned improvements | |||||
| 3. Help tab in the gadget, pulling from `?regex` but with some | |||||
| navigation. | |||||
| - I may add `stringi` functions to the list of available functions in | |||||
| the **Output** tab. | |||||
| 4. Tab to interactively explore output of varying regex-applying | |||||
| functions. In other words, see what `stringr::str_locate_all` or | |||||
| `stringr::str_match_all` or `grep` or `grepl` return when applying | |||||
| the regex to your text. | |||||
| - I would like to add the regex/function options for the functions in | |||||
| the **Output** tab, similar to the options present in the **Regex** | |||||
| tab. |
| cheatsheet <- tibble::tribble( | |||||
| ~category, ~group, ~regexp, ~text, | |||||
| "character classes", "regular", "<code>.</code>", "any character except newline", | |||||
| "character classes", "regular", "<code>\\w</code> <code>\\d</code> <code>\\s</code>", "word, digit, whitespace", | |||||
| "character classes", "regular", "<code>\\W</code> <code>\\D</code> <code>\\S</code>", "not word, digit, whitespace", | |||||
| # "character classes", "regular", "<code>\\p{property name}</code>", "matches character with unicode property, like <code>\\p{Uppercase}</code>, see <a href=\"http://www.unicode.org/reports/tr44/#Property_Index.\">unicode property list</a>.", | |||||
| "character classes", "regular", "<code>[abc]</code>", "any of a, b or c", | |||||
| "character classes", "regular", "<code>[^abc]</code>", "not a, b, or c", | |||||
| "character classes", "regular", "<code>[a-g]</code> <code>[1-3]</code>", "character between a & g or 1 & 3", | |||||
| "character classes", "regular", "<code>[\\^\\-]</code>", "matches <code>-</code> or <code>\\</code>", | |||||
| "character classes", "pre-built", "Used inside <code>[]</code>", "Example <code>[[:digit:]AX]</code> matches all digits and A and X", | |||||
| "character classes", "pre-built", "<code>[:punct:]</code>", "punctuation", | |||||
| "character classes", "pre-built", "<code>[:alpha:]</code>", "letters", | |||||
| "character classes", "pre-built", "<code>[:lower:]</code>", "lowercase letters", | |||||
| "character classes", "pre-built", "<code>[:upper:]</code>", "uppercase letters", | |||||
| "character classes", "pre-built", "<code>[:digit:]</code>", "digits", | |||||
| "character classes", "pre-built", "<code>[:xdigit:]</code>", "hex digits", | |||||
| "character classes", "pre-built", "<code>[:alnum:]</code>", "letters and numbers", | |||||
| "character classes", "pre-built", "<code>[:cntrl:]</code>", "control characters", | |||||
| "character classes", "pre-built", "<code>[:graph:]</code>", "letters, numbers, and punctuation", | |||||
| "character classes", "pre-built", "<code>[:print:]</code>", "letters, numbers, punctuation, and whitespace", | |||||
| "character classes", "pre-built", "<code>[:space:]</code>", "space characters (basically equivalent to <code>\\s</code>)", | |||||
| "character classes", "pre-built", "<code>[:blank:]</code>", "space and tab", | |||||
| "anchors", NA, "<code>^</code>", "start of string", | |||||
| "anchors", NA, "<code>$</code>", "end of string", | |||||
| "anchors", NA, "<code>\\b</code>", "word boundary", | |||||
| "anchors", NA, "<code>\\B</code>", "not-word boundary", | |||||
| "anchors", NA, "<code>\\A</code>", "stringr multiline: match start of the input", | |||||
| "anchors", NA, "<code>\\z</code>", "stringr multiline: match end of the input", | |||||
| "anchors", NA, "<code>\\Z</code>", "stringr multiline: match end of the input, but before final line terminator (if it exists)", | |||||
| "escaped characters", "general", "<code>\\.</code>", "dot", | |||||
| "escaped characters", "general", "<code>\\*</code>", "asterisk", | |||||
| "escaped characters", "general", "<code>\\\\</code>", "backslash", | |||||
| "escaped characters", "general", "<code>\\t</code>", "tab", | |||||
| "escaped characters", "general", "<code>\\n</code>", "linefeed", | |||||
| "escaped characters", "general", "<code>\\r</code>", "carriage return", | |||||
| "escaped characters", "hex", "<code>\\xhh</code>", "2 hex digits", | |||||
| "escaped characters", "hex", "<code>\\x{hhhh}</code>", "1-6 hex digits", | |||||
| "escaped characters", "hex", "<code>\\uhhhh</code>", "4 hex digitis", | |||||
| "escaped characters", "hex", "<code>\\Uhhhhhhhh</code>", "8 hex digits", | |||||
| "escaped characters", "hex", "<code>\\N{name}</code>", "Name of unicode character, e.g. <code>\\N{grinning face}</code>", | |||||
| "escaped characters", "control characters", "<code>\\a</code>", "bell", | |||||
| "escaped characters", "control characters", "<code>\\cX</code>", "match a control-X character", | |||||
| "escaped characters", "control characters", "<code>\\e</code>", "escape (<code>\\u001B</code>)", | |||||
| "escaped characters", "control characters", "<code>\\f</code>", "form feed (<code>\\u000C</code>)", | |||||
| "escaped characters", "control characters", "<code>\\0ooo</code>", "octal character where \"ooo\" is 1-3 octal digits", | |||||
| "groups", NA, "<code>(abc)</code>", "capture group", | |||||
| "groups", NA, "<code>\\1</code>, <code>\\2</code>, <code>\\3</code> ...", "backreference to group 1, group 2, etc.", | |||||
| "groups", NA, "<code>(?:abc)</code>", "non-capturing group, e.g. <code>\"gr(?:e|a)y\")</code>", | |||||
| "groups", NA, "<code>(?=abc)</code>", "postive lookahead; matches are followed by <code>abc</code> (non-capturing)", | |||||
| "groups", NA, "<code>(?!abc)</code>", "negative lookahead; matches are not followed by <code>abc</code> (non-capturing)", | |||||
| "groups", NA, "<code>(?<=abc)</code>", "positive lookbehind; matches are preceeded by <code>abc</code> (non-capturing)", | |||||
| "groups", NA, "<code>(?<!abc)</code>", "negative lookbehind; matches are not preceeded by <code>abc</code> (non-capturing)", | |||||
| "groups", NA, "<code>(?>abc)</code>", "atomic-match; no back-tracking if later matches fail", | |||||
| "quantifiers", NA, "<code>a*</code>", "0 or more", | |||||
| "quantifiers", NA, "<code>a+</code>", "1 or more", | |||||
| "quantifiers", NA, "<code>a?</code>", "0 or 1", | |||||
| "quantifiers", NA, "<code>a{n}</code>", "exactly n times", | |||||
| "quantifiers", NA, "<code>a{n,}</code>", "n or more times", | |||||
| "quantifiers", NA, "<code>a{n,m}</code>", "n-m times", | |||||
| "quantifiers", NA, "add <code>+</code>", "makes match possessive", | |||||
| "quantifiers", NA, "add <code>?</code>", "makes match non-greedy", | |||||
| "quantifiers", NA, "<code>ab|cd</code>", "match ab or cd", | |||||
| "quantifiers", NA, "<code>w(?:o|a)ke</code>", "use non-capturing group for precedence" | |||||
| ) | |||||
| th, | |||||
| td { | |||||
| padding: 10px 13px; | |||||
| text-align: left; | |||||
| border-bottom: 1px solid #E1E1E1; } | |||||
| th:first-child, | |||||
| td:first-child { | |||||
| padding-left: 0; } | |||||
| th:last-child, | |||||
| td:last-child { | |||||
| padding-right: 0; } | |||||
| #help-sidebar { | |||||
| padding-top: 5px; | |||||
| padding-left: 10px; | |||||
| } | |||||
| #help-sidebar ul { | |||||
| list-style-type: none; | |||||
| font-size: 1.1em; | |||||
| } | |||||
| #help-sidebar li { | |||||
| list-style: none; | |||||
| } | |||||
| #help-sidebar .header li { | |||||
| padding: 3px; | |||||
| } | |||||
| #help-sidebar a { | |||||
| display: block; | |||||
| width: 100%; | |||||
| text-decoration: none; | |||||
| text-align: left; | |||||
| padding: 3px; | |||||
| } | |||||
| #help-sidebar .subgroup { | |||||
| padding-left: 0px; | |||||
| } | |||||
| #help-sidebar .subgroup a { | |||||
| padding-left: 15px; | |||||
| } | |||||
| #help-sidebar a:hover { | |||||
| background-color: #eee; | |||||
| text-decoration: none; | |||||
| } |
| Name: Regexplain Selection | |||||
| Description: Build a regexp for use on selected text | |||||
| Binding: regexplain_addin | |||||
| Interactive: true | |||||
| Name: Regexplain File | |||||
| Description: Choose a file for which to build a regexp | |||||
| Binding: regexplain_file | |||||
| Interactive: true | |||||
| Name: Regexplain Cheetsheet | |||||
| Description: Regex Cheatsheet Quickreference | |||||
| Binding: regexplain_cheatsheet | |||||
| Interactive: false |
| .results { | .results { | ||||
| font-family: "Monaco", "Inconsolata", monospace; | font-family: "Monaco", "Inconsolata", monospace; | ||||
| padding-top: 5px; | |||||
| color: #888888; | |||||
| } | |||||
| .gadget-result { | |||||
| border: 1px solid #ccc; | |||||
| border-radius: 0.5rem; | |||||
| padding: 8px; | |||||
| overflow-wrap: break-word; | |||||
| } | } | ||||
| .group { | .group { | ||||
| border-bottom: 2px solid; | border-bottom: 2px solid; | ||||
| color: black; | |||||
| padding: 0px; | padding: 0px; | ||||
| } | } | ||||
| } | } | ||||
| .pad06 { | .pad06 { | ||||
| padding-bottom: 18px; | padding-bottom: 18px; | ||||
| margin-bottom: 18px; | |||||
| } | |||||
| .pad07 { | |||||
| padding-bottom: 21px; | |||||
| margin-bottom: 21px; | |||||
| } | |||||
| .pad08 { | |||||
| padding-bottom: 23px; | |||||
| margin-bottom: 23px; | |||||
| } | |||||
| .pad09 { | |||||
| padding-bottom: 25px; | |||||
| margin-bottom: 25px; | |||||
| } | } |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/regex_gadget.R | |||||
| \name{regex_gadget} | |||||
| \alias{regex_gadget} | |||||
| \title{regexplain gadget} | |||||
| \usage{ | |||||
| regex_gadget(text = NULL, start_page = if (is.null(text)) "Text" else | |||||
| "Regex") | |||||
| } | |||||
| \arguments{ | |||||
| \item{text}{Text to explore in gadget (editable using interface)} | |||||
| \item{start_page}{Open gadget to this tab, one of `"Text"`, `"Regex"`, | |||||
| `"Output"`, or `"Help"`} | |||||
| } | |||||
| \description{ | |||||
| regexplain gadget | |||||
| } |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/rstudio_addins.R | |||||
| \name{regexplain_addin} | |||||
| \alias{regexplain_addin} | |||||
| \title{regexplain_addin} | |||||
| \usage{ | |||||
| regexplain_addin() | |||||
| } | |||||
| \description{ | |||||
| regexplain_addin | |||||
| } | |||||
| \keyword{internal} |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/regex_help.R | |||||
| \name{regexplain_cheatsheet} | |||||
| \alias{regexplain_cheatsheet} | |||||
| \title{Regex Cheatsheet Quick Reference} | |||||
| \usage{ | |||||
| regexplain_cheatsheet() | |||||
| } | |||||
| \description{ | |||||
| Regex Cheatsheet Quick Reference | |||||
| } |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/rstudio_addins.R | |||||
| \name{regexplain_file} | |||||
| \alias{regexplain_file} | |||||
| \title{regexplain file loader} | |||||
| \usage{ | |||||
| regexplain_file() | |||||
| } | |||||
| \description{ | |||||
| regexplain file loader | |||||
| } | |||||
| \keyword{internal} |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/run_regex.R | |||||
| \name{run_regex} | |||||
| \alias{run_regex} | |||||
| \title{Extract matched groups from regexp} | |||||
| \usage{ | |||||
| run_regex(text, pattern, ignore.case = FALSE, perl = FALSE, fixed = FALSE, | |||||
| useBytes = FALSE, invert = FALSE) | |||||
| } | |||||
| \arguments{ | |||||
| \item{text}{Text to search} | |||||
| \item{pattern}{regexp} | |||||
| \item{ignore.case}{if \code{FALSE}, the pattern matching is \emph{case | |||||
| sensitive} and if \code{TRUE}, case is ignored during matching.} | |||||
| \item{perl}{logical. Should Perl-compatible regexps be used?} | |||||
| \item{fixed}{logical. If \code{TRUE}, \code{pattern} is a string to be | |||||
| matched as is. Overrides all conflicting arguments.} | |||||
| \item{useBytes}{logical. If \code{TRUE} the matching is done | |||||
| byte-by-byte rather than character-by-character. See | |||||
| \sQuote{Details}.} | |||||
| \item{invert}{logical. If \code{TRUE} return indices or values for | |||||
| elements that do \emph{not} match.} | |||||
| } | |||||
| \description{ | |||||
| Extract matched groups from regexp | |||||
| } |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/shiny_modified_inputs.R | |||||
| \name{textAreaInputAlt} | |||||
| \alias{textAreaInputAlt} | |||||
| \title{Modified Text Area Input} | |||||
| \usage{ | |||||
| textAreaInputAlt(inputId, label, value = "", width = NULL, height = NULL, | |||||
| cols = NULL, rows = NULL, placeholder = NULL, resize = NULL, | |||||
| is_code = TRUE) | |||||
| } | |||||
| \arguments{ | |||||
| \item{inputId}{The \code{input} slot that will be used to access the value.} | |||||
| \item{label}{Display label for the control, or \code{NULL} for no label.} | |||||
| \item{value}{Initial value.} | |||||
| \item{width}{The width of the input, e.g. \code{'400px'}, or \code{'100\%'}; | |||||
| see \code{\link{validateCssUnit}}.} | |||||
| \item{height}{The height of the input, e.g. \code{'400px'}, or | |||||
| \code{'100\%'}; see \code{\link{validateCssUnit}}.} | |||||
| \item{cols}{Value of the visible character columns of the input, e.g. | |||||
| \code{80}. If used with \code{width}, \code{width} will take precedence in | |||||
| the browser's rendering.} | |||||
| \item{rows}{The value of the visible character rows of the input, e.g. | |||||
| \code{6}. If used with \code{height}, \code{height} will take precedence in | |||||
| the browser's rendering.} | |||||
| \item{placeholder}{A character string giving the user a hint as to what can | |||||
| be entered into the control. Internet Explorer 8 and 9 do not support this | |||||
| option.} | |||||
| \item{resize}{Which directions the textarea box can be resized. Can be one of | |||||
| \code{"both"}, \code{"none"}, \code{"vertical"}, and \code{"horizontal"}. | |||||
| The default, \code{NULL}, will use the client browser's default setting for | |||||
| resizing textareas.} | |||||
| \item{is_code}{Should the text input be considered verbatim code input?} | |||||
| } | |||||
| \description{ | |||||
| Standard [shiny::textAreaInput()] with additional `is_code` parameter, added | |||||
| code font style for the input text and with `autocomplete`, `autocorrect`, | |||||
| `autocapitalize` and `spellcheck` set to `off` or `false`. | |||||
| } |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/shiny_modified_inputs.R | |||||
| \name{textInputCode} | |||||
| \alias{textInputCode} | |||||
| \title{Modified Text Input} | |||||
| \usage{ | |||||
| textInputCode(inputId, label, value = "", width = NULL, | |||||
| placeholder = NULL) | |||||
| } | |||||
| \arguments{ | |||||
| \item{inputId}{The \code{input} slot that will be used to access the value.} | |||||
| \item{label}{Display label for the control, or \code{NULL} for no label.} | |||||
| \item{value}{Initial value.} | |||||
| \item{width}{Width of `shiny-input-container` div.} | |||||
| \item{placeholder}{A character string giving the user a hint as to what can | |||||
| be entered into the control. Internet Explorer 8 and 9 do not support this | |||||
| option.} | |||||
| } | |||||
| \description{ | |||||
| Standard [shiny::textInput()] with additional `width` parameter, added code | |||||
| font style for the input text and with `autocomplete`, `autocorrect`, | |||||
| `autocapitalize` and `spellcheck` set to `off` or `false`. | |||||
| } |
| library(testthat) | |||||
| library(regexplain) | |||||
| test_check("regexplain") |
| context("test-wrap_regex.R") | |||||
| test_that("wrap_regex generally works", { | |||||
| expect_equal(wrap_regex("(a)(b)"), | |||||
| "<span class=\"g01\">(a)</span><span class=\"g02\">(b)</span>") | |||||
| }) | |||||
| test_that("wrap_regex doesn't add parens", { | |||||
| expect_equal(wrap_regex("\\ba"), "\\ba") | |||||
| }) |