branch: externals/php-fill
commit 6fc5d91be264f30eaa14acf83398ef6f884cf7f3
Author: Ariel Del Valle Lozano <[email protected]>
Commit: Ariel Del Valle Lozano <[email protected]>
First commit.
---
.gitignore | 23 +
Eask | 20 +
LICENSE | 674 +++++++++++++++++++++
Makefile | 90 +++
README.org | 50 ++
images/backspace-and-del.gif | Bin 0 -> 313816 bytes
images/nosqueez.gif | Bin 0 -> 217700 bytes
images/refill.gif | Bin 0 -> 1167142 bytes
images/return.gif | Bin 0 -> 246145 bytes
images/string-literal.gif | Bin 0 -> 190589 bytes
php-fill.el | 824 ++++++++++++++++++++++++++
test/erts/backward-delete.erts | 164 +++++
test/erts/break-long-string-literl-apart.erts | 268 +++++++++
test/erts/c-fill-paragraph-nosqueez.erts | 40 ++
test/erts/c-fill-paragraph.erts | 100 ++++
test/erts/delete-forward.erts | 111 ++++
test/erts/fill-paragraph.erts | 99 ++++
test/erts/fill-string-literal.erts | 59 ++
test/erts/newline.erts | 44 ++
test/erts/refill-mode.erts | 178 ++++++
test/erts/set-local-variables.erts | 17 +
test/erts/stitch-string-parts-together.erts | 96 +++
test/php-fill-test.el | 106 ++++
23 files changed, 2963 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..b5aa721d65
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+# ignore these directories
+/.git
+/recipes
+
+# ignore log files
+/.log
+
+# ignore generated files
+*.elc
+
+# eask packages
+.eask/
+dist/
+
+# packaging
+*-autoloads.el
+*-pkg.el
+
+# OS generated
+.DS_Store
+
+# emacs recovery files
+\#*#
\ No newline at end of file
diff --git a/Eask b/Eask
new file mode 100644
index 0000000000..92740547db
--- /dev/null
+++ b/Eask
@@ -0,0 +1,20 @@
+;; -*- mode: eask; lexical-binding: t -*-
+
+(package "php-fill"
+ "1.0.0"
+ "Additional fill commands for PHP code editing")
+
+(website-url "https://github.com/arielenter/php-fill.el")
+(keywords "php" "languages" "tools" "convenience")
+
+(package-file "php-fill.el")
+
+(script "test" "echo \"Error: no test specified\" && exit 1")
+
+(source 'gnu)
+(source 'nongnu)
+
+(development
+ (depends-on "php-mode"))
+
+(depends-on "emacs" "27.1")
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000..f288702d2f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://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
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..7f9de2e9aa
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,90 @@
+##
+# Eask generated template Makefile
+#
+# File located in
https://github.com/emacs-eask/template-elisp/blob/master/Makefile
+##
+
+EMACS ?= emacs
+EASK ?= eask
+
+.PHONY: clean package install compile test checkdoc lint
+
+# CI entry point
+#
+# You can add or remove any commands here
+#
+# (Option 1): Basic for beginner, only tests for package's installation
+# ci: clean package install compile
+# (Option 2): Advanced for a high-quality package
+#ci: clean package install compile checkdoc lint test
+
+ci: clean compile checkdoc lint test
+
+# Build an package artefact, default to `dist` folder
+#
+# This is used to test if your package can be built correctly before the
+# package installation.
+package:
+ @echo "Packaging..."
+ $(EASK) package
+
+# Install package
+#
+# If your package is a single file package, you generally wouldn't need to
+install:
+ @echo "Installing..."
+ $(EASK) install
+
+# Byte-compile package
+#
+# Compile all your package .el files to .elc
+compile:
+ @echo "Compiling..."
+ $(EASK) compile
+
+# Run regression tests
+#
+# The default test is `ert`; but Eask also support other regression test!
+# See
https://emacs-eask.github.io/Getting-Started/Commands-and-options/#-linting
+test:
+ @echo "Testing..."
+ $(EASK) install-deps --dev
+ $(EASK) test ert ./test/*.el
+
+# Run checkdoc
+#
+# See https://www.emacswiki.org/emacs/CheckDoc
+checkdoc:
+ @echo "Checking documentation..."
+ $(EASK) lint checkdoc --strict
+
+# Lint package metadata
+#
+# See https://github.com/purcell/package-lint
+lint:
+ @echo "Linting..."
+ $(EASK) lint package
+
+# Generate autoloads file
+#
+# NOTE: This is generally unnecessary
+autoloads:
+ @echo "Generating autoloads..."
+ $(EASK) autoloads
+
+# Generate -pkg file
+#
+# NOTE: This is generally unnecessary
+pkg-file:
+ @echo "Generating -pkg file..."
+ $(EASK) pkg-file
+
+# Clean up
+#
+# This will clean all the entire workspace including the following folders
+# and files
+#
+# - .eask folder (sandbox)
+# - all .elc files
+clean:
+ $(EASK) clean all
diff --git a/README.org b/README.org
new file mode 100644
index 0000000000..d23cab4e32
--- /dev/null
+++ b/README.org
@@ -0,0 +1,50 @@
+* php-fill.el
+
+Additional fill commands for PHP code editing.
+
+** Fills string literals by breaking them into smaller ones.
+
+[[images/string-literal.gif]]
+
+** Conditionally use ‘NOSQUEEZ’ on c and c++ style comments.
+
+[[images/nosqueez.gif]]
+
+** Use “<return>” to break or add a new line to string literals and comments.
+
+[[image/return.gif]]
+
+** Use “<backspace>” or “<delete>” at the end and at the beginning to join
them.
+
+[[image/backspace-and-del.gif]]
+
+** Minor mode Php-Refill.
+
+[[image/refill.gif]]
+
+** Added it to your init.el
+
+We recommend using this package with a major mode for PHP, like the ones
supply by packages like
[[https://elpa.nongnu.org/nongnu/php-mode.html][php-mode]] and
[[https://elpa.gnu.org/packages/phps-mode.html][phps-mode]], to get the
indentation right and for the hook.
+
+The following example uses ‘php-mode’, but if a different major mode were to
be used, just change ‘php-mode’ with something else like ‘phps-mode’ instead.
+
+While in the process of being accepted in either
[[https://elpa.gnu.org/][elpa.gnu.org]] or
[[https://elpa.nongnu.org/][elpa.nongnu.org]], please download ‘php-fill.el’
and add it by using its holding location, shown here as "~/.emacs.d/lisp/" as
an example.
+
+#+BEGIN_SRC emacs-lisp
+ (add-to-list 'load-path (expand-file-name "~/.emacs.d/lisp/"))
+ (use-package php-fill
+ :load-path "~/.emacs.d/lisp/"
+ ;; :custom
+ ;; (php-fill-fill-column 120) ;; Default is 80.
+ ;; (php-fill-sentence-end-double-space t) ;; Default is nil.
+ ;; (php-fill-nosqueeze-c-comments nil) ;; Default is t
+ ;; (php-fill-nosqueeze-c++-comments t) ;; Default is nil
+ :hook
+ (php-mode . php-fill-set-local-variables)
+ :bind
+ (:map php-mode-map
+ ("M-q" . php-fill-paragraph)
+ ("<return>" . php-fill-newline)
+ ("<backspace>" . php-fill-backward-delete)
+ ("<delete>" . php-fill-delete-forward)))
+#+END_SRC
diff --git a/images/backspace-and-del.gif b/images/backspace-and-del.gif
new file mode 100644
index 0000000000..95e6f31618
Binary files /dev/null and b/images/backspace-and-del.gif differ
diff --git a/images/nosqueez.gif b/images/nosqueez.gif
new file mode 100644
index 0000000000..da5d7bdff3
Binary files /dev/null and b/images/nosqueez.gif differ
diff --git a/images/refill.gif b/images/refill.gif
new file mode 100644
index 0000000000..afad29061e
Binary files /dev/null and b/images/refill.gif differ
diff --git a/images/return.gif b/images/return.gif
new file mode 100644
index 0000000000..a2021c8750
Binary files /dev/null and b/images/return.gif differ
diff --git a/images/string-literal.gif b/images/string-literal.gif
new file mode 100644
index 0000000000..e8295dcfbb
Binary files /dev/null and b/images/string-literal.gif differ
diff --git a/php-fill.el b/php-fill.el
new file mode 100644
index 0000000000..2389a88ee4
--- /dev/null
+++ b/php-fill.el
@@ -0,0 +1,824 @@
+;;; php-fill.el --- Additional fill commands for PHP code editing -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2026 Free Software Foundation, Inc
+
+;; Author: Ariel Del Valle Lozano <[email protected]>
+;; Maintainer: Ariel Del Valle Lozano <[email protected]>
+;; URL: https://github.com/arielenter/php-fill.el
+;; Version: 1.0.0
+;; Package-Requires: ((emacs "27.1"))
+;; Keywords: php, languages, tools, convenience
+
+;; This file is not part of GNU Emacs.
+
+;; 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
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; Heavily base on fill-paragraph, refill-mode and c-fill-paragraph.
+;;
+;;
+
+;;; Code:
+
+(defun php-fill-paragraph (&optional only-one-line-up)
+ "Like \\[c-fill-paragraph] but string literals are handled in a\n\
+different way (tailor made for PHP) and a small customizable option was
+added for comments.
+
+String literals are handled using command \\[php-fill-string-literal].
+
+In the case of comments, two global variables decide whether or not the
+argument NOSQUEEZ of function `fill-delete-newlines' will be used either
+on C or C++ style comments or both. See command
+\\[php-fill-c-fill-paragraph] for additional information.
+
+Optional argument ONLY-ONE-LINE-UP will be passed down to
+`php-fill-string-literal'."
+ (interactive)
+ (let ((php-fill-literal (php-fill-get-literal)) literal-limits)
+ (setq literal-limits (car php-fill-literal))
+ (if (or (not literal-limits) (equal literal-limits 'string))
+ (php-fill-string-literal only-one-line-up)
+ (call-interactively 'php-fill-c-fill-paragraph))))
+
+(require 'cc-engine)
+
+(defun php-fill-get-literal ()
+ "Return both the literal type and the positions of its delimiters as a\n\
+con.
+
+This code is taken from `c-mask-paragraph' with little changes.
+
+Since this values may be requested more than once on the same context by
+different functions, running the complete process again may be
+unnecessary. With this in mind, a method to avoid this was created that
+consist on declaring variable `php-fill-literal' non globally using
+`let' and assigning to it the returned value of a called of this
+function. This way, if this function is run again in the same
+context (within the aforementioned `let'), it'll simply return the
+already established value of the variable `php-fill-literal'."
+ (if (boundp 'php-fill-literal)
+ php-fill-literal
+ (c-save-buffer-state ()
+ (save-restriction
+ ;; Widen to catch limits correctly.
+ (widen)
+ (let ((literal-limits (c-literal-limits nil nil)))
+ (cons (c-literal-type literal-limits) literal-limits))))))
+
+(defun php-fill-string-literal (&optional only-one-line-up)
+ "Fill PHP's quoted string literals by breaking them into smaller ones.
+
+Works similarly to how functions like `fill-paragraph' and
+`c-fill-paragraph' break lines of text after they have passed the
+`current-fill-column', but while `c-fill-paragraph' breaks the lines of
+text within the confinements of the string literal's content, keeping
+it's delimiters and simplify adding newlines to it, this function
+instead breaks long quoted string literals (either single or double
+quoted) into smaller ones, one per line, if said string literal is
+located at the end of a line. This is done using word wrap rules,
+meaning that string literals are not broken in the middle of words, but
+right after the closet space preceding a word. Each subsequent line
+will start with a dot and a space, representing the concatenation of the
+smaller string literals. Indentation is done using the command
+\\[indent-according-to-mode], for this reason, it's highly recommended
+to use some PHP dedicated major mode like the ones offer by packages
+‘php-mode’ and ‘phps-mode’.
+
+It isn't necessary to have the pointer inside the string literal located
+at the end of the line, neither at any of its subsequent parts, to have
+said string structure filled. As long as the pointer is located in a
+line ending on a string literal, that string literal would become the
+subject of the fill process. A line is considered to end on a string
+literal only if both string delimiting quotes are located on the same
+line, meaning string literals containing one or more literal line breaks
+are not supported. Escape sequence line breaks ‘\\n’ are fine. It
+might also be pertinent to mention that neither ‘heredoc’ nor ‘nowdoc’
+string literal PHP's syntax are supported, only quoted (either single or
+double) strings are.
+
+The objective is that none of the content of the lines should over pass
+the `current-fill-column' columns, but it's worth pointing out that the
+length of a line doesn't depend exclusively of the string literal's
+content. It is however, the only part that would be looked to be broken
+apart. The rest of the line content like the indentation, any content
+before the string literal, the string literal's delimiting quotes and
+possible statement ending semicolon or an array value separation coma
+ending the line, are part of what establishes the length of the line
+holding the string literal, but they will not be touch in any way. So
+even if the string literal content doesn't cross over the
+`current-fill-column', if at least its ending quote, a a semicolon, or a
+coma ending the line do, the string literal will be looked to be broken
+just the same. Another interesting scenario is what happens if the rest
+of the line content before the string literal pushes the beginning of
+this last mentioned, too close or even passing `current-fill-column',
+since as aforementioned before, words aren't cut in the middle. In an
+scenario as described before, this command will look to break the string
+content at the closest suitable breakable place from the beginning of
+said string.
+
+Another caveat is that (commonly) ‘fill’ prefixed functions trim white
+spaces on both left and right ends, but that won't be done to the string
+literal content. Also multiple spaces between words are normally
+‘squeezed’ into just one, but this won't be done either. In fact, in
+order for a dedicated string literal concatenating line to be considered
+part of the previous one for the fill process, the previous string
+content must end on a space.
+
+Concatenated string literals are considered part of the same structure
+only if they used the same quote type (double or single quotes), and
+only if a concatenated string literal covers the entire line, meaning,
+if a line contains more than one string literal being concatenated, they
+won't be considered as part of the same string in the fill process.
+
+If two string literal shared a line, for instance on a concatenation or
+when array values are being defined, only last string literal will be
+filled.
+
+Optional argument ONLY-ONE-LINE-UP value will be passed down to command
+\\[php-fill-stitch-string-parts-together] as is."
+ (interactive)
+ (when (php-fill-supported-string-literal-in-line)
+ (php-fill-stitch-string-parts-together only-one-line-up)
+ (php-fill-break-long-string-literal-apart)))
+
+(rx-let ((anything-before-string-literal (: (*? nonl) (or (not ?\\) bol)))
+ ;; Matches \\, \" and \\\" but not \\" nor \\\\"
+ (scaped-sequence (: ?\\ nonl))
+ (scaped-sqnc-or-not-a-quote
+ (quote) (or scaped-sequence (not (or quote "\n" ?\\))))
+ (scaped-sqnc-or-not-a-quote-nor-a-space
+ (quote) (or scaped-sequence (not (or quote "\n" ?\\ " "))))
+ (string-literal-with-any-or-no-content
+ (quote) (: quote (* (scaped-sqnc-or-not-a-quote quote)) quote))
+ (quote-version (quote)
+ (string-literal-with-any-or-no-content quote))
+ (either-version (or (quote-version ?') (quote-version ?\")))
+ (may-or-maynot-end-a-statement-or-an-array-value
+ (: (? (in ",;")) eol))
+ (breakable-string-literal
+ (quote) (: (group-n 101 quote)
+ (* (scaped-sqnc-or-not-a-quote quote)) " "
+ (+ (scaped-sqnc-or-not-a-quote-nor-a-space quote))
+ (* " ") quote))
+ (concatenation (: (* (in " \t")) ". "))
+ (two-lines-concatenation
+ (quote) (: quote (*? (scaped-sqnc-or-not-a-quote quote)) " "
+ (group-n 100 quote "\n" concatenation quote)
+ (* (scaped-sqnc-or-not-a-quote quote)) quote)))
+
+ (defconst php-fill-line-ends-with-a-string-literal-regexp
+ (rx anything-before-string-literal either-version
+ may-or-maynot-end-a-statement-or-an-array-value)
+ "Looking at a line ending on a string literal with any or no content.
+
+When looking from the beginning of a line, a match of this regular
+expression will indicate that the current line ends in a quoted string
+literal with any or no content, regardless of how the rest of the line
+starts with or if the string literal occupies the entire line. After
+said string literal, there may or may not be either a semicolon or a
+coma, representing an statement end or part of an array values
+assignment, but nothing more, only the end of the line.")
+
+ (rx-let ((quote-version (quote) (breakable-string-literal quote)))
+ (defconst php-fill-line-ends-with-breakable-str-regexp
+ (rx anything-before-string-literal either-version
+ may-or-maynot-end-a-statement-or-an-array-value)
+ "Looking at a line ending on a breakable string literal.
+
+When looking from the beginning of a line, a match of this regular
+expression will indicate that the current line ends with a breakable
+quoted string literal, regardless of how the line starts with or if the
+string literal occupies the entire line. After said string literal,
+there may or may not be either a semicolon or a coma, representing an
+statement end or part of an array values assignment, but nothing more,
+only the end of the line.
+
+In the context of this package, a string literal is considered breakable
+if its content posses at least one word succeeding a space, which is the
+criteria used by the function `php-fill-break-long-string-literal-apart'
+to established where a string literal can be broken when the content of
+the line holding it over pass the `current-fill-column' position.
+Considering this, a string literal can't be broken by
+`php-fill-break-long-string-literal-apart' if there isn't a word that
+succeeds a space."))
+
+ (rx-let ((quote-version (quote) (two-lines-concatenation quote)))
+ (defconst php-fill-two-lines-concatenation-regexp
+ (rx anything-before-string-literal either-version
+ may-or-maynot-end-a-statement-or-an-array-value)
+ "Looking at two string literals being concatenated on two separated\n\
+lines.
+
+When looking from the beginning of a line, a match of this regular
+expression will indicate that the current line ends with a quoted string
+literal whose contend ends with a space, regardless of what the line
+starts with or if the string literal occupies the entire line. Said
+string literal may or may not have any additional content. What follows
+is a new line, and said line is dedicated to a string concatenation of a
+secondary string literal that uses the exact same quote type than the
+first one. The contend of this second line is a possible indentation,
+followed by a dot, one space, and a string literal that covers the rest
+of the line. A possible semicolon or a coma may follow, but nothing
+else except for the end of the line. The second string literal content
+does not matter, it can even be empty.
+
+This regexp establishes the requirements that function
+`php-fill-stitch-two-lines-concatenation' uses to stitch two string
+literals together into one."))
+
+ (defconst php-fill-string-concatenation-dedicated-line-regexp
+ (rx concatenation either-version
+ may-or-maynot-end-a-statement-or-an-array-value)
+ "Looking at a line dedicated to a string concatenation.
+
+When looking from the beginning of a line, a match of this regular
+expression will indicate that the current line is dedicated to a string
+concatenation, meaning that the line starts with a possible indentation,
+followed by a dot, one space, and a quoted string literal that covers
+the rest of the line. A possible semicolon or a coma may follow, but
+nothing else except for the end of the line. The string literal content
+does not matter, it can even be empty.
+
+A string concatenation dedicated line, tells function
+`php-fill-supported-string-literal-in-line' that the line might be part
+of a supported `php-fill-stitch-two-lines-concatenation' string literal
+concatenation, but further analysis will be needed to be sure."))
+
+(defun php-fill-supported-string-literal-in-line ()
+ "Return t if current line ends on a supported fill-able string literal\n\
+candidate for command \\[php-fill-string-literal].
+
+The reason they are yet only candidates is because some other factors
+are needed to be checked later on, to be sure if they can, or more
+precisely, if they need to be filled. Some of this other factors
+include, but are not limited to the lines length and possible
+concatenation with other supported string literals."
+ (save-restriction
+ (widen)
+ (let ((literal (php-fill-get-literal)) literal-type literal-limits)
+ (setq literal-type (car literal) literal-limits (cdr literal))
+ (and (not (memq literal-type '(c c++ pound)))
+ (or (not literal-type)
+ ;; At this point, ‘literal-type’ value would have to be
+ ;; ‘string’, in which case we should check whether or not
+ ;; current line is not inside a multi line string, since
+ ;; there is no reason to act on a code that's inside a
+ ;; string literal. We can discard this by checking if
+ ;; the string literal, point is currently within, does
+ ;; not extend more than one line, meaning both delimiters
+ ;; should be located in the same line.
+ (php-fill-lit-limits-are-in-the-same-line literal-limits))
+ (save-excursion
+ (beginning-of-line)
+ (and (looking-at
+ php-fill-line-ends-with-a-string-literal-regexp)
+ (or (looking-at
+ php-fill-line-ends-with-breakable-str-regexp)
+ (looking-at
+ php-fill-two-lines-concatenation-regexp)
+ (looking-at
+
php-fill-string-concatenation-dedicated-line-regexp))))))))
+
+(defun php-fill-lit-limits-are-in-the-same-line (literal-limits)
+ "Check if both LITERAL-LIMITS are located in the same line."
+ (= (line-number-at-pos (car literal-limits))
+ (line-number-at-pos (cdr literal-limits))))
+
+(defun php-fill-stitch-string-parts-together (&optional only-one-line-up)
+ "Stitch together multiple string literals being concatenated if they\n\
+meet an specified criteria.
+
+Same way \\[c-fill-paragraph] uses `fill-delete-newlines' to unfill c
+and c++ style comments so that their content can then be readjusted or
+more precisely refilled, when substantial changes have been made, this
+function is used to stitch together string literals concatenations that
+follow the format expressed in the regular expression constant
+`php-fill-two-lines-concatenation-regexp', so that they can be broken
+again by command \\[php-fill-break-long-string-literal-apart] as part of
+the whole fill process of the \\[php-fill-string-literal] command.
+
+To this end, this function looks up and down from the initial point to
+check what lines have the correct concatenation format to stitch string
+literals together. It's possible that there might be no string literal
+concatenations up or down from point to stitch together with.
+
+Some times, it is not needed to stitch together the entire structure of
+supported string literal concatenations, if you know exactly where a
+change is being made. This is the case of function
+`php-fill-refill-paragraph' that is used by minor mode
+`php-fill-refill-mode', whenever a change is done. For this cases, if a
+non nil value is given to ‘ONLY-ONE-LINE-UP’ argument, this function
+will only look to stitch one line up from the initial point, since it's
+the only string literal up from point that may be affected from a change
+done at the line where point is located.
+
+As an interactive function, this function can be used on it's own. In
+combination with \\[php-fill-break-long-string-literal-apart] it will
+pretty much end up doing what \\[php-fill-string-literal] does in a
+single swift call.
+
+One idea this command might be useful on its own will be (if
+`php-fill-refill-mode' is not wanted) to use this command first, edit a
+string literal as a whole (possibly using `visual-line-mode' on), and
+then use \\[php-fill-break-long-string-literal-apart]."
+ (interactive)
+ (while (php-fill-stitch-two-lines-concatenation))
+ (catch 'exit-while
+ (while (php-fill-stitch-two-lines-concatenation 0)
+ (when only-one-line-up (throw 'exit-while t)))))
+
+(defun php-fill-stitch-two-lines-concatenation (&optional n pos)
+ "Stitch together two string literals being concatenated if they meet\n\
+an specified criteria.
+
+This function does the heavy lifting for
+\\[php-fill-stitch-string-parts-together], \\[php-fill-backward-delete]
+and \\[php-fill-delete-forward] commands, when it comes to stitching
+supported string literal concatenations together into one.
+
+First it moves pointer to either the beginning of the current line or
+the previous one depending on the N argument value. Then it checks if
+the two lines in front meet the requirements set by the regular
+expression `php-fill-two-lines-concatenation-regexp' to get them stitch
+together.
+
+Depending on whether or not POS argument value is nil or the value of
+the point position is given to it, argument POS's value will be taken
+into account to stitch the two concatenated string literals together or
+not."
+ (save-restriction
+ (widen)
+ (save-excursion
+ (beginning-of-line n)
+ (if (not (and (looking-at php-fill-two-lines-concatenation-regexp)
+ (or (not pos)
+ (and (= 0 n) (= (match-end 100) pos))
+ (and (or (= 1 n) (not n))
+ (or (= (match-beginning 100) pos)
+ (= (- (match-beginning 100) 1) pos))))))
+ nil
+ (replace-match "" nil nil nil 100) t))))
+
+(defun php-fill-break-long-string-literal-apart ()
+ "Breaks long string literals into smaller ones if they are located at\n\
+the end of a line which content crosses the `current-fill-column'.
+
+Checks if current line ends with a breakable quoted string literal and
+if the line content over passes `current-fill-column', it breaks the
+aforementioned string literal into smaller ones, one per line. Each
+line containing the smaller string literals will start with the PHP's
+syntax to concatenate it with the previous string, meaning a dot follow
+by a space, and it's content will be correctly indented according to the
+major mode, for which we recommend using one for PHP like the ones
+offer by packages like ‘php-mode’ and ‘phps-mode’.
+
+This is only the last of the two steps done by
+\\[php-fill-string-literal] to full refilled string literals, being the
+first one \\[php-fill-stitch-string-parts-together].
+
+All other descriptions from this package mentioned that the string
+literals are broken at the end of a space that precedes a word, but this
+description might not be clear enough. In the context of this package,
+a word means any amount of characters between alphanumeric, symbols, or
+anything else not being a space nor the end delimiter quote of the
+string literal being worked on. It might be worth to mention that
+escaped quotes are accounted for so they won't be mistaken with the
+ending quote.
+
+As an interactive function, this function can be used on it's own. In
+combination with \\[php-fill-stitch-string-parts-together] it will
+pretty much end up doing what \\[php-fill-string-literal] does in a
+single swift call.
+
+One idea this command might be useful on its own will be (if
+`php-fill-refill-mode' is not wanted) to use
+\\[php-fill-stitch-string-parts-together] command first, edit a string
+literal as a whole (possibly using `visual-line-mode' on), and then use
+this command at the end.
+
+Function `current-fill-column' was chosen to be used for no other reason
+that it is the function used by command \\[fill-paragraph]."
+ (interactive)
+ (save-restriction
+ (widen)
+ (indent-according-to-mode)
+ (let (quote breakable-point beg-column break-column)
+ (save-excursion
+ (while (and (progn (end-of-line) (> (current-column)
+ (current-fill-column)))
+ (progn (beginning-of-line)
+ (looking-at
+ php-fill-line-ends-with-breakable-str-regexp)))
+ (goto-char (match-beginning 101))
+ (setq beg-column (current-column))
+ ;; break-column has to be at least 2 characters less from
+ ;; current-fill-column to fit a space and the ending quote.
+ (setq break-column (if (> beg-column (- (current-fill-column) 2))
+ beg-column (- (current-fill-column) 2)))
+ (move-to-column break-column)
+ (when (not quote) (setq quote (match-string 101))
+ ;; The breaking point that'll be looked for, is a space
+ ;; preceding any other character not being a space nor
+ ;; the string literal ending quote.
+ (setq breakable-point (concat " [^ " quote "]")))
+ (while (and (> (current-column) beg-column)
+ (not (looking-at breakable-point)))
+ (backward-char))
+ (when (not (looking-at breakable-point))
+ (move-to-column break-column)
+ (forward-char)
+ (while (not (looking-at breakable-point))
+ (forward-char)))
+ ;; By now, break point would have to have been found (for
+ ;; example ' w') now move forward and break it.
+ (forward-char)
+ (insert quote "\n. " quote)
+ (indent-according-to-mode))))))
+
+(defcustom php-fill-nosqueeze-c-comments t
+ "\\[php-fill-c-fill-paragraph] decides whether or not to use\n\
+\\[php-fill-c-fill-paragraph-nosqueez] on c style comments depending on
+the value of this variable.
+
+A t default value was chosen so that Phpdoc blocks (which are c style
+comments) using spaces to alight columns (like when using the '@param'
+tag), would not loose said alignment if \\[php-fill-paragraph] or
+\\[php-fill-c-fill-paragraph] are used on them. If this way of
+formatting doc blocks values isn't used, setting a nil value might be
+preferred.
+
+See command \\[php-fill-c-fill-paragraph-nosqueez] for additional
+information."
+ :type 'boolean
+ :group 'php-fill)
+
+(defcustom php-fill-nosqueeze-c++-comments nil
+ "\\[php-fill-c-fill-paragraph] decides whether or not to use\n\
+\\[php-fill-c-fill-paragraph-nosqueez] on c++ style comments depending
+on the value of this variables."
+ :type 'boolean
+ :group 'php-fill)
+
+(require 'cc-cmds)
+
+(defun php-fill-c-fill-paragraph (&optional arg)
+ "Use two variables to determine to use \\[c-fill-paragraph] or\n\
+\\[php-fill-c-fill-paragraph-nosqueez] on current comment.
+
+This two are `php-fill-nosqueeze-c-comments' for the c style commends
+and `php-fill-nosqueeze-c++-comments' for the c++ style ones.
+
+As an example, if pointer is located within a C++ styled comment and
+`php-fill-nosqueeze-c++-comments' is not nil, then command
+\\[php-fill-c-fill-paragraph-nosqueez] will be used to fill it.
+Otherwise if `php-fill-nosqueeze-c++-comments' were to be nil, then
+`c-fill-paragraph' would be used on its place.
+
+ARG attribute is pass down to `c-fill-paragraph' if it ends up being
+called.
+
+WARNING: If optional prefix ARG is not nil, then `c-fill-paragraph' will
+be used regardless of variables `php-fill-nosqueeze-c-comments' and
+`php-fill-nosqueeze-c++-comments''s values, since a non nil ARG value
+tells `c-fill-paragraph' to use full justification on the comments
+being filled, which ends up making NOSQUEEZ irrelevant."
+ (interactive "*P")
+ (let ((literal-type (car (php-fill-get-literal))))
+ (if (and (not arg)
+ (or (and (equal literal-type 'c)
+ php-fill-nosqueeze-c-comments)
+ (and (equal literal-type 'c++)
+ php-fill-nosqueeze-c++-comments)))
+ (php-fill-c-fill-paragraph-nosqueez)
+ (c-fill-paragraph arg))))
+
+(defun php-fill-c-fill-paragraph-nosqueez ()
+ "Force function `fill-delete-newlines' to be called with a non nil\n\
+NOSQUEEZ argument once \\[c-fill-paragraph] is called within this
+function.
+
+\\[c-fill-paragraph] uses `fill-delete-newlines' to unfill c and c++
+style comments so that their content can then be re-adjusted (refilled)
+when a pertinent amount of changes have been made. While this is done,
+normally if multiple spaces exist between words, they are ‘squeezed’, or
+more precisely, replaced with a single one. This might not always be
+desirable. For instance, while writing a Phpdoc block (which are c
+style comments) with '@param' tags, we might want to alight their values
+creating plain text columns using spaces. In this scenario, ‘squeeze’
+would destroy said alignment if command \\[c-fill-paragraph] were to be
+used on its own while point is located in said doc block comment."
+ (interactive)
+ (unwind-protect
+ (progn
+ (advice-add 'fill-delete-newlines :filter-args
+ #'php-fill-delete-newlines-filter-args-advice)
+ (c-fill-paragraph))
+ (advice-remove
+ 'fill-delete-newlines
+ #'php-fill-delete-newlines-filter-args-advice)))
+
+(defun php-fill-delete-newlines-filter-args-advice (arg)
+ "Argument-filter advice that replace NOSQUEEZ with a non nil value.
+
+ARG contains all the arguments caught before function
+`fill-delete-newlines' is executed. Then NOSQUEEZ is exclusively edited
+to a t value, the arguments are repackaged into a list, and finally
+returned back to `fill-delete-newlines' called."
+ (pcase-let ((`(,from ,to ,justify ,nosqueeze ,squeeze-after) arg))
+ (setq nosqueeze t)
+ (list from to justify nosqueeze squeeze-after)))
+
+(define-minor-mode php-fill-refill-mode
+ "Like \\[refill-mode] but handles C, C++ style comments, and quoted \
+PHP's string literals.
+
+For this purpose, function `php-fill-paragraph' is used."
+ :init-value nil
+ :lighter " Php-Refill"
+ :interactive 'php-mode 'phps-mode
+ :group 'php
+ (if php-fill-refill-mode
+ (progn
+ (add-hook 'after-change-functions
+ #'php-fill-refill-after-change-function nil t)
+ (add-hook 'post-command-hook
+ #'php-fill-refill-post-command-function nil t))
+ (remove-hook 'after-change-functions
+ #'php-fill-refill-after-change-function t)
+ (remove-hook 'post-command-hook
+ #'php-fill-refill-post-command-function t)))
+
+(defvar-local php-fill-refill-promise-to-doit nil
+ "This variable is used by `php-fill-refill-mode' to avoid doing the\n\
+refill process more times that needed.
+
+Check function `php-fill-refill-after-change-function' for additional
+information.")
+
+(defun php-fill-refill-after-change-function (_beg _end _len)
+ "After-change function used by minor mode `php-fill-refill-mode'.
+
+Notice that the refill process is not called here yet, only a promise to
+do so later on by the function `php-fill-refill-post-command-function'
+is set. This allows not having to run the refill process multiple times
+if the current command being run makes multiple changes.
+
+Notice as well that changes done by an undo progress should not trigger
+refill, otherwise undo won't be able to reverse back what the refill
+process did right before (since it would be redone right back), or other
+undesirable effects might arise.
+
+Another case is while commenting and un-commenting code, since filling
+said code will make it loose its format, which is inferred to be an
+undesirable behavior.
+
+Function \\[php-fill-newline] is a special case, since we only want to
+suppress the refill process if it's used to break a string literal in
+two. The reason is that, if the refill process were not suppressed and
+if a split were to be made right after a space, the user could get
+confused since it would appear as if nothing happened, since right after
+the string literals is broken, it will immediately be reattached back
+together. For this reason, \\[php-fill-newline] would set variable
+`php-fill-refill-promise-to-doit' back no nil in this scenario."
+ (unless (or undo-in-progress
+ (memq this-command '(comment-or-uncomment-region
+ comment-region uncomment-region)))
+ (setq php-fill-refill-promise-to-doit t)))
+
+(defun php-fill-refill-post-command-function ()
+ "Post-command function used by minor mode `php-fill-refill-mode' to do\n\
+the refill process conditionally.
+
+Uses variable `php-fill-refill-promise-to-doit' to check if a change was made
+by the last called command, and if so, call the refill function then.
+
+Notice that the `php-fill-refill-promise-to-doit' must be return back to
+nil to conserved the mechanism that prevents the refill process from
+being run unless a change has been made by the last command.
+
+Check function `php-fill-refill-after-change-function' for additional
+information."
+ (when php-fill-refill-promise-to-doit ; there was a change
+ (php-fill-refill-paragraph)
+ (setq php-fill-refill-promise-to-doit nil)))
+
+(defun php-fill-refill-paragraph ()
+ "Used by `php-fill-refill-mode' to refill current comment or string\n\
+literal.
+
+Notices that the fill function won't be run if point is located at the
+end of the line and the previous character is a space. Otherwise, while
+composing a comment, a refill will delete the white space that might
+have just been added to it, which will just prevent adding additional
+content to the comment being work on.
+
+Notice also that command \\[php-fill-paragraph]'s argument
+ONLY-ONE-LINE-UP is send with a value of t. This will end up telling
+function `php-fill-stitch-string-parts-together' that is not necessary
+to stitch back all possible supported concatenation string literals
+present above point's current line, only one line up is enough. The
+reason for this, is that any change made in the current line, can only
+possibly affect the right before string literal fill. See command
+\\[php-fill-stitch-string-parts-together] for additional information.
+This assumes you've been using `php-fill-refill-mode' from the start
+while the current string structure was being created, otherwise if it
+already existed, you might want to use \\[php-fill-paragraph] on its own
+to get the entire structure readjust and refilled before continuing
+editing it."
+ (when (save-excursion (backward-char 1) (not (looking-at " $")))
+ (php-fill-paragraph t)))
+
+(defun php-fill-newline ()
+ "Add a newline in a particular way, if point is located within doc\n\
+block or a string literal.
+
+If point is located inside a quoted (double or single quoted) string
+literal, said string literal will be broken into two from the point this
+command is called from. The second string literal will be placed in the
+next line, and it will share the same quote type used by the original.
+Also, the PHP's code corresponding to the concatenation of the two,
+meaning a dot and a space, will be added at the beginning of the new
+line. And finally the new line will be indented using the method
+provided by the major mode.
+
+Something to note is that string literals broken this way might get
+stitch back together if command \\[php-fill-paragraph] is used on them
+or if a change is made on them in minor mode `php-fill-refill-mode'.
+This will happen when a string literal is broken after a space, since
+it's the criteria used by the aforementioned functions to stitch string
+literals together that are being concatenated. If this is undesired,
+you can make sure to split a string literal content at a place other
+than a space.
+
+Lastly, if point is located on a Phpdoc block, a new line follow by and
+asterisk will be inserted and the line will be indented. Depending if
+the insertion was done in the middle of a paragraph and not at the end
+of one, another line will be added, adding also and asterisk and
+indenting the line, making it so that the original paragraph is split
+into two paragraphs separated by and empty line."
+ (interactive)
+ (save-restriction
+ (widen)
+ (let ((literal (php-fill-get-literal)) literal-type literal-limits)
+ (setq literal-type (car literal) literal-limits (cdr literal))
+ (cond
+ ((and (equal literal-type 'string)
+ (php-fill-lit-limits-are-in-the-same-line literal-limits)
+ (save-excursion (goto-char (car literal-limits))
+ (looking-at "['\"]")))
+ (let ((quote (match-string 0)))
+ (insert quote "\n. " quote)
+ (indent-according-to-mode))
+ ; Avoid refill
+ (setq php-fill-refill-promise-to-doit nil))
+ ((and (equal literal-type 'c)
+ (save-excursion (beginning-of-line)
+ (looking-at "[ \t]*")))
+ (insert "\n*")
+ (indent-according-to-mode)
+ (when (not (looking-at " *$"))
+ (insert "\n*")
+ (indent-according-to-mode)))
+ (t (newline))))))
+
+(defun php-fill-backward-delete ()
+ "Depending on point's position, stitch the content of two strings\n\
+literals or two prefixed comment lines together.
+
+Depending if point is located at the beginning of a second quoted string
+literal of two being concatenated, or at the beginning of a second line
+of a c or c++ style prefixed comment that succeeds another, a backward
+delete will be done in a particular way.
+
+In the case of a supported two string literals being concatenated (see
+`php-fill-stitch-two-lines-concatenation'), both string literals will be
+stitch together before command \\[c-electric-backspace] is executed.
+
+In the case of point being at the beginning of a prefixed comment
+content, said prefix, meaning '#' and '//' for c++ style comments or '*'
+for Phpdoc block's c style comments, including their preceding spaces
+and line indentation, will be deleted first before
+`c-electric-backspace' is called, ending up stitching previous comment
+line with current line, word with word. For this to happen, previous
+line must also be of the same kind of comment and prefix. See
+`php-fill-stitch-together-two-comment-lines' for additional information."
+ (interactive)
+ (when (not (region-active-p))
+ (let ((literal-type (car (php-fill-get-literal))))
+ (cond
+ ((memq literal-type '(c c++))
+ (php-fill-stitch-together-two-comment-lines 0))
+ ((php-fill-supported-string-literal-in-line)
+ (php-fill-stitch-two-lines-concatenation 0 (point))))))
+ (call-interactively 'c-electric-backspace))
+
+(rx-let ((comment-start (st) (: (* (in " \t")) st))
+ (comment-version
+ (st) (: (comment-start st) (* nonl) "\n"
+ (group-n 1 (comment-start st) (* " ")) (not " ")))
+ (all-versions (or (comment-version "*") (comment-version "#")
+ (comment-version "//"))))
+
+ (defun php-fill-stitch-together-two-comment-lines (&optional n)
+ "Depending on point's position, stitch two prefixed comment lines\n\
+together.
+
+This function verifies if pointer is located at the beginning or at the
+end (depending of the value of argument N) of two consecutive prefixed c
+or c++ commends of the same kind and with the same prefix ('#', '//' or
+'*'). If that's the case, stitch them together before either a backward
+or forward delete is performed by either \\[php-fill-backward-delete] or
+\\[php-fill-delete-forward] respectively.
+
+The objective is to seemingly thread the content of comments as if they
+were a continuous line, without indention, prefix and subsequent spaces,
+working well when used in conjunction with `php-fill-refill-mode' minor
+mode or even without it."
+ (let ((pos (point)))
+ (save-excursion
+ (when (and (progn (beginning-of-line n)
+ (looking-at (rx all-versions)))
+ (or (and n (= 0 n) (= (match-end 1) pos))
+ (and (or (not n) (= 1 n))
+ (= (- (match-beginning 1) 1) pos))))
+ (replace-match "" nil nil nil 1))))))
+
+(defun php-fill-delete-forward ()
+ "Depending on point's position, stitch the content of two strings\n\
+literals or two prefixed comment lines together.
+
+Depending if point is located at the end of the content of the first
+quoted string literal of two being concatenated, or at the end of the
+content of the first line of a c or c++ styled and prefixed comment that
+precedes another one, a backward delete will be done in a particular
+way.
+
+In the case of a supported two string literals being concatenated (see
+`php-fill-stitch-two-lines-concatenation'), both string literals will be
+stitch together before command \\[delete-forward-char] is called.
+
+In the case of point being at the end of a prefixed comment that
+precedes another one, the beginning of said second commented line which
+includes its prefix, meaning '#' and '//' for c++ style comments or '*'
+for Phpdoc block's c style comments, their succeeding spaces and the
+line indentation will be deleted first before command
+\\[delete-forward-char] is called interactively, ending up stitching
+current comment line with next one, word with word. For this to happen,
+previous line must also be of the same kind of comment and have the same
+prefix. See `php-fill-stitch-together-two-comment-lines' for additional
+information."
+ (interactive)
+ (when (not (region-active-p))
+ (let ((literal-type (car (php-fill-get-literal))))
+ (cond
+ ((memq literal-type '(c c++))
+ (php-fill-stitch-together-two-comment-lines))
+ ((php-fill-supported-string-literal-in-line)
+ (php-fill-stitch-two-lines-concatenation 1 (point))))))
+ (call-interactively 'delete-forward-char))
+
+(defcustom php-fill-sentence-end-double-space nil
+ "Determines what local value `sentence-end-double-space' will \n\
+received from command \\[php-fill-set-local-variables] on the current
+buffer."
+ :type 'boolean
+ :group 'php-fill)
+
+(defcustom php-fill-fill-column 80
+ "Determines what local value `fill-column' will received from command\n\
+\\[php-fill-set-local-variables] on the current buffer.
+
+It's important to say that this customizable variable doesn't replace
+`fill-column'. `fill-column' it's still used as the value look up to
+fill any content. The purpose of this variable is to ease the process
+of setting up a default `fill-column' for PHP files, through the use of
+the command `php-fill-set-local-variables' and a hook to a major mode
+like the ones provided by packages ‘php-mode’ or ‘phps-mode’."
+ :type 'integer
+ :group 'php-fill)
+
+(defun php-fill-set-local-variables ()
+ "Set current buffer's values of variables `sentence-end-double-space'\n\
+and `fill-column'.
+
+To this end, the values of `php-fill-sentence-end-double-space' and
+`php-fill-fill-column' are used."
+ (interactive)
+ (setq-local sentence-end-double-space php-fill-sentence-end-double-space)
+ (setq-local fill-column php-fill-fill-column))
+
+(provide 'php-fill)
+;;; php-fill.el ends here
diff --git a/test/erts/backward-delete.erts b/test/erts/backward-delete.erts
new file mode 100644
index 0000000000..f01d220924
--- /dev/null
+++ b/test/erts/backward-delete.erts
@@ -0,0 +1,164 @@
+Name: Stitches two string being concatenated if placed at the beginning of the
second one
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (php-fill-backward-delete))
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . '|amet, consectetur.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit|amet, consectetur.';
+=-=-=
+
+Name: Won't stitch two concatenated string literals if they don't meet the
requirements
+=-=
+$stringVar = 'Lorem ipsum dolor sit'
+ . '|amet, consectetur.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit'
+ . |amet, consectetur.';
+=-=-=
+
+Name: Stitches two Phpdoc block's lines together.
+=-=
+/**
+ * @param string $short Quite long
+ * |description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite long|description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Stitches two commented lines together whit '//' prefix
+=-=
+// Lorem ipsum dolor sit amet
+// |consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+// Lorem ipsum dolor sit amet|consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Stitches two commented lines together whit '#' prefix
+=-=
+# Lorem ipsum dolor sit amet
+# |consectetur adipiscing elit. Fusce
+# vel luctus tellus.
+=-=
+# Lorem ipsum dolor sit amet|consectetur adipiscing elit. Fusce
+# vel luctus tellus.
+=-=-=
+
+Name: Diferent types of prefix won't be stitched together
+=-=
+# Lorem ipsum dolor sit amet
+// |consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+# Lorem ipsum dolor sit amet
+//|consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Previus line must also be a comment line
+=-=
+$stringVar = "Some other line";
+// |consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+$stringVar = "Some other line";
+//|consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Backward delete must be done on the beginning of the first word
+=-=
+// Lorem ipsum dolor sit amet
+//| consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+// Lorem ipsum dolor sit amet
+/| consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Backward delete must be done on the beginning of the first word on
Phpdoc blocks paragraphs
+=-=
+/**
+ * @param string $short Quite long
+ * | description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite long
+ * | description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: After stitching two strings, c-electric-backspace is called interactively
+Code: (lambda ()
+ (php-mode)
+ (let ((current-prefix-arg '(4)))
+ (call-interactively 'php-fill-backward-delete)))
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . '|amet, consectetur adipiscing.';
+=-=
+$stringVar = 'Lorem ipsum dolor |amet, consectetur adipiscing.';
+=-=-=
+
+Name: After stitching two comment lines, c-electric-backspace is called
interactively
+=-=
+// Lorem ipsum dolor sit amet
+// |consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+// Lorem ipsum dolor sit a|consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Doesn't work if there is an active region
+Code: (lambda ()
+ (php-mode)
+ (push-mark (point) nil t)
+ (goto-char (- (point) 4))
+ (activate-mark)
+ (php-fill-backward-delete))
+=-=
+/**
+ * @param string $short Quite long
+ * desc|ription
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite long
+ * |ription
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Doesn't work if there is an active region inside a string literal
+=-=
+$stringVar = 'Lorem ipsum dolor sit '\n . 'ame|t, consectetur.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '\n . |t, consectetur.';
+=-=-=
diff --git a/test/erts/break-long-string-literl-apart.erts
b/test/erts/break-long-string-literl-apart.erts
new file mode 100644
index 0000000000..b9014641a0
--- /dev/null
+++ b/test/erts/break-long-string-literl-apart.erts
@@ -0,0 +1,268 @@
+WARNING Some lines might appear longer than what should be posible because of
the point-char
+
+Name: Long string literal with point inside.
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 80)
+ (php-fill-break-long-string-literal-apart))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui auctor,
bibendum dui vitae, susc|ipit sapien. In porta ante id metus placerat viverra.
Aliquam a massa eu ante tempus semper. Nullam ac eros gravida, viverra ipsum
eu, egestas dolor.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce '
+ . 'vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui '
+ . 'auctor, bibendum dui vitae, susc|ipit sapien. In porta ante id metus '
+ . 'placerat viverra. Aliquam a massa eu ante tempus semper. Nullam ac eros
'
+ . 'gravida, viverra ipsum eu, egestas dolor.';
+=-=-=
+
+Name: Long string literal with point outside but on the same line.
+=-=
+$stri|ngVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui auctor,
bibendum dui vitae, suscipit sapien. In porta ante id metus placerat viverra.
Aliquam a massa eu ante tempus semper. Nullam ac eros gravida, viverra ipsum
eu, egestas dolor.';
+=-=
+$stri|ngVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce '
+ . 'vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui '
+ . 'auctor, bibendum dui vitae, suscipit sapien. In porta ante id metus '
+ . 'placerat viverra. Aliquam a massa eu ante tempus semper. Nullam ac eros
'
+ . 'gravida, viverra ipsum eu, egestas dolor.';
+=-=-=
+
+Name: String must be long enought
+=-=
+$stringVar = 'Lorem ip|sum dolor sit amet, consectetur adipiscing elit.
Fusceas';
+=-=-=
+
+Name: Even if only statement ender semicolon passes, it will be broken apart.
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Fu|sceass';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
+ . 'Fu|sceass';
+=-=-=
+
+Name: Even if the coma that separates values on an array passes.
+=-=
+$arrayVar = [
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel
lu|ctuas',
+ 4
+];
+=-=
+$arrayVar = [
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel '
+ . 'lu|ctuas',
+ 4
+];
+=-=-=
+
+Name: Even if only the string literal delimiter passes.
+=-=
+$arrayVar = [
+ 'example' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit
fu|sces'
+];
+=-=
+$arrayVar = [
+ 'example' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit '
+ . 'fu|sces'
+];
+=-=-=
+
+Name: The string literal must exist at the end of the line
+=-=
+$stringVar = 'Lorem i|psum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus.' . $stringTwo;
+=-=-=
+
+Name: Long string literal with quote type double as its delimiters.
+=-=
+$stringVar = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui auctor,
bibendum dui vitae, susc|ipit sapien. In porta ante id metus placerat viverra.
Aliquam a massa eu ante tempus semper. Nullam ac eros gravida, viverra ipsum
eu, egestas dolor.";
+=-=
+$stringVar = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce "
+ . "vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui "
+ . "auctor, bibendum dui vitae, susc|ipit sapien. In porta ante id metus "
+ . "placerat viverra. Aliquam a massa eu ante tempus semper. Nullam ac eros
"
+ . "gravida, viverra ipsum eu, egestas dolor.";
+=-=-=
+
+Name: right-margin text property influences on the fill
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 80)
+ (set-right-margin (point-min) (point-max) 30)
+ (php-fill-break-long-string-literal-apart)
+ (set-text-properties (point-min) (point-max) nil))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui auctor,
bibendum dui vitae, susc|ipit sapien. In porta ante id metus placerat viverra.
Aliquam a massa eu ante tempus semper. Nullam ac eros gravida, viverra ipsum
eu, egestas dolor.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, '
+ . 'consectetur adipiscing elit. Fusce vel '
+ . 'luctus tellus, non varius ante. Nam et '
+ . 'arcu augue. Nulla ac dui auctor, bibendum '
+ . 'dui vitae, susc|ipit sapien. In porta ante '
+ . 'id metus placerat viverra. Aliquam a '
+ . 'massa eu ante tempus semper. Nullam ac '
+ . 'eros gravida, viverra ipsum eu, egestas '
+ . 'dolor.';
+=-=-=
+
+Name: Fill column can be bigger
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 120)
+ (php-fill-break-long-string-literal-apart))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante. Nam et arcu augue. Nulla ac dui auctor,
bi|bendum dui vitae, suscipit sapien. In porta ante id metus placerat viverra.
Aliquam a massa eu ante tempus semper. Nullam ac eross gravida, viverra ipsum
eu, egestas dolor.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante. Nam '
+ . 'et arcu augue. Nulla ac dui auctor, bi|bendum dui vitae, suscipit
sapien. In porta ante id metus placerat '
+ . 'viverra. Aliquam a massa eu ante tempus semper. Nullam ac eross
gravida, viverra ipsum eu, egestas dolor.';
+=-=-=
+
+Name: Fill column can be smaller
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-break-long-string-literal-apart))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fu|sce
vel luctus tellus, non varius ante.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fu|sce vel luctus '
+ . 'tellus, non varius ante.';
+=-=-=
+
+Name: Spaces are neither trim nor squeezed.
+=-=
+$stringVar = " Lorem ipsum dolor sit amet, consectetur
ad|ipiscing elit . ";
+=-=
+$stringVar = " Lorem ipsum "
+ . "dolor sit amet, "
+ . "consectetur ad|ipiscing "
+ . "elit . ";
+=-=-=
+
+Name: String must be breakable
+=-=
+$stringVar = 'Loremipsumdolorsitametconsec ';
+=-=-=
+
+Name: Handdle scaped quotes just fine (pairs of a backslash follow by a
character)
+=-=
+$stringVar = "Lorem ipsum \"dolor sit amet\\\", consectetur \"adi|piscing\"
elit. Fusce vel luctus tellus.";
+=-=
+$stringVar = "Lorem ipsum \"dolor "
+ . "sit amet\\\", consectetur "
+ . "\"adi|piscing\" elit. Fusce "
+ . "vel luctus tellus.";
+=-=-=
+
+Name: Can't be fool with a fake scaped quote (double backslashes cancel each
other)
+=-=
+$stringVar = "Lore|m ipsum \\"dolor sit amet, \\\\\\"consectetur adipiscing
elit. Fusce vel luctus tellus";
+=-=-=
+
+Name: Long words are not cut in the middle.
+=-=
+class SomeClass
+{
+ function someMethod ()
+ {
+ if (true)
+ {
+ $array = [
+ 'Loremipsumdolorsitamet, et con|secteturadipiscingelit.
Fuscevelluctustellus, non varius ante.'
+ ];
+ }
+ }
+}
+=-=
+class SomeClass
+{
+ function someMethod ()
+ {
+ if (true)
+ {
+ $array = [
+ 'Loremipsumdolorsitamet, '
+ . 'et '
+ . 'con|secteturadipiscingelit. '
+ . 'Fuscevelluctustellus, '
+ . 'non varius '
+ . 'ante.'
+ ];
+ }
+ }
+}
+=-=-=
+
+Name: If string literal beginning passes fill-column, text will be broken as
soon as posible.
+=-=
+class SomeClass
+{
+ function someMethod ()
+ {
+ while (true)
+ {
+ if (true)
+ {
+ $array = [
+ [
+ [
+ [
+ 'exa|mple_key_long' => 'Lorem ipsum dolor sit
amet, consectetur adipiscing elit. Fusce vel luctus tellus, non varius ante.'
+ ]
+ ]
+ ]
+ ];
+ break;
+ }
+ }
+ }
+}
+=-=
+class SomeClass
+{
+ function someMethod ()
+ {
+ while (true)
+ {
+ if (true)
+ {
+ $array = [
+ [
+ [
+ [
+ 'exa|mple_key_long' => 'Lorem '
+ . 'ipsum '
+ . 'dolor '
+ . 'sit '
+ . 'amet, '
+ . 'consectetur '
+ . 'adipiscing '
+ . 'elit. '
+ . 'Fusce '
+ . 'vel '
+ . 'luctus '
+ . 'tellus, '
+ . 'non '
+ . 'varius '
+ . 'ante.'
+ ]
+ ]
+ ]
+ ];
+ break;
+ }
+ }
+ }
+}
+=-=-=
+
+Name: Most anything is cosidered a word.
+Point-Char: ¡
+=-=
+$string¡Var = "\|@á#~½¬ {[]é}\?=) \|@í#~½¬ {[]ó}\?=) (/&ú%$·!ª (/&ñ%$·!ª";
+=-=
+$string¡Var = "\|@á#~½¬ {[]é}\?=) "
+ . "\|@í#~½¬ {[]ó}\?=) (/&ú%$·!ª "
+ . "(/&ñ%$·!ª";
+=-=-=
diff --git a/test/erts/c-fill-paragraph-nosqueez.erts
b/test/erts/c-fill-paragraph-nosqueez.erts
new file mode 100644
index 0000000000..0d85da9002
--- /dev/null
+++ b/test/erts/c-fill-paragraph-nosqueez.erts
@@ -0,0 +1,40 @@
+Name: Fills c++ style comments without squeezing spaces between words (prefix
//)
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-c-fill-paragraph-nosqueez))
+=-=
+// Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+// Lo|rem ipsum dolor sit amet,
+// consectetur adipiscing elit.
+// Fusce vel luctus tellus.
+=-=-=
+
+Name: Fills c++ style comments without squeezing spaces between words (prefix
#)
+=-=
+# Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+# Lo|rem ipsum dolor sit amet,
+# consectetur adipiscing elit.
+# Fusce vel luctus tellus.
+=-=-=
+
+Name: Fills c style comments without squeezing spaces between words (prefix *)
+=-=
+/**
+ * @param string $short Quite l|ong description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite l|ong
+ * description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
diff --git a/test/erts/c-fill-paragraph.erts b/test/erts/c-fill-paragraph.erts
new file mode 100644
index 0000000000..aff4e820eb
--- /dev/null
+++ b/test/erts/c-fill-paragraph.erts
@@ -0,0 +1,100 @@
+Name: Doesn't squeez spaces in c++ style comments if variable
php-fill-nosqueeze-c++-comments is not nil
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (customize-set-variable 'php-fill-nosqueeze-c++-comments t)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c-comments)
+ (php-fill-c-fill-paragraph))
+=-=
+// Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+// Lo|rem ipsum dolor sit amet,
+// consectetur adipiscing elit.
+// Fusce vel luctus tellus.
+=-=-=
+
+Name: Doesn't squeez spaces in c style comments if variable
php-fill-nosqueeze-c-comments is not nil, which is the defualt value
+=-=
+/**
+ * @param string $short Quite l|ong description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite l|ong
+ * description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Squeezes spaces in c++ style comments if variable
php-fill-nosqueeze-c++-comments is null, which is the default value
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (customize-set-variable 'php-fill-nosqueeze-c-comments nil)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c++-comments)
+ (php-fill-c-fill-paragraph))
+=-=
+// Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+// Lo|rem ipsum dolor sit amet,
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Squeezes spaces in c style comments if variable
php-fill-nosqueeze-c-comments is nil
+=-=
+/**
+ * @param string $short Quite l|ong description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite l|ong
+ * description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: If the command is prefixed then the value of
php-fill-nosqueeze-c++-comments will be ignored and the c++ style comment will
be justified
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (customize-set-variable 'php-fill-nosqueeze-c++-comments t)
+ (customize-set-variable 'php-fill-nosqueeze-c-comments t)
+ (let ((current-prefix-arg '(4)))
+ (call-interactively 'php-fill-c-fill-paragraph)))
+=-=
+// Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+// Lo|rem ipsum dolor sit amet,
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: If the command is prefixed then the value of
php-fill-nosqueeze-c-comments will be ignored and the c style comment will be
justified
+=-=
+/**
+ * @param string $short Quite l|ong description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite l|ong
+ * description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
diff --git a/test/erts/delete-forward.erts b/test/erts/delete-forward.erts
new file mode 100644
index 0000000000..cce9daff49
--- /dev/null
+++ b/test/erts/delete-forward.erts
@@ -0,0 +1,111 @@
+Name: Stitches two string being concatenated if placed at the end of the first
one before delete-forward-char is called
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (call-interactively 'php-fill-delete-forward))
+=-=
+$stringVar = 'Lorem ipsum dolor sit |'
+ . 'amet, consectetur.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit |met, consectetur.';
+=-=-=
+
+Name: Stitches two string being concatenated if placed at the beginning of the
last space
+=-=
+$stringVar = 'Lorem ipsum dolor sit| '
+ . 'amet, consectetur.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit|amet, consectetur.';
+=-=-=
+
+Name: Won't stitch two concatenated string literals if they don't meet the
requirements
+=-=
+$stringVar = 'Lorem ipsum dolor sit|'
+ . 'amet, consectetur.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit|
+ . 'amet, consectetur.';
+=-=-=
+
+Name: Stitches two Phpdoc block's lines together.
+=-=
+/**
+ * @param string $short Quite long|
+ * description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite long|description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Stitches two commented lines together whit '//' prefix
+=-=
+// Lorem ipsum dolor sit amet|
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+// Lorem ipsum dolor sit amet|consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Stitches two commented lines together whit '#' prefix
+=-=
+# Lorem ipsum dolor sit amet|
+# consectetur adipiscing elit. Fusce
+# vel luctus tellus.
+=-=
+# Lorem ipsum dolor sit amet|consectetur adipiscing elit. Fusce
+# vel luctus tellus.
+=-=-=
+
+Name: Diferent types of prefix won't be stitched together
+=-=
+# Lorem ipsum dolor sit amet|
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+# Lorem ipsum dolor sit amet|// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Succeeding line must also be a comment line
+=-=
+$stringVar = "Some other line";|
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+$stringVar = "Some other line";|// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Won't work on an active region
+Code: (lambda ()
+ (php-mode)
+ (push-mark (point) t t)
+ (goto-char (+ (point) 4))
+ (activate-mark)
+ (php-fill-delete-forward))
+=-=
+/**
+ * @param string $short Quite |long
+ * description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite |
+ * description
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
diff --git a/test/erts/fill-paragraph.erts b/test/erts/fill-paragraph.erts
new file mode 100644
index 0000000000..e8d5e421af
--- /dev/null
+++ b/test/erts/fill-paragraph.erts
@@ -0,0 +1,99 @@
+Name: Uses php-fill-c-paragraph to fill c++ style comments.
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c++-comments)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c-comments)
+ (php-fill-paragraph))
+=-=
+// Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+// Lo|rem ipsum dolor sit amet,
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Uses php-fill-c-paragraph to fill c style comments.
+=-=
+/**
+ * @param string $short Quite l|ong description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite l|ong
+ * description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Uses php-fill-string-literal to fill string literals.
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fu|sce
vel luctus tellus, non varius ante.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fu|sce vel luctus '
+ . 'tellus, non varius ante.';
+=-=-=
+
+Name: A prefix justify c++ style comments.
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (customize-set-variable 'php-fill-nosqueeze-c++-comments t)
+ (customize-set-variable 'php-fill-nosqueeze-c-comments t)
+ (let ((current-prefix-arg '(4)))
+ (call-interactively 'php-fill-paragraph)))
+=-=
+// Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus.
+=-=
+// Lo|rem ipsum dolor sit amet,
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: A prefix justify c style comments.
+=-=
+/**
+ * @param string $short Quite l|ong description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite l|ong
+ * description,
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Optional argument ONLY-ONE-LINE-UP will be passed down to
php-fill-string-literal
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-paragraph t))
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing in porta ante id metus placerat viverra '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, n|on varius ante, Nam Nullam ac eros gravida,'
+ . 'et arcu augue. Nulla ac dui '
+ . 'auctor, bibendum dui vitae';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing in porta ante id metus placerat viverra '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante, Nam '
+ . 'Nullam ac eros gravida,'
+ . 'et arcu augue. Nulla ac dui '
+ . 'auctor, bibendum dui vitae';
+=-=-=
diff --git a/test/erts/fill-string-literal.erts
b/test/erts/fill-string-literal.erts
new file mode 100644
index 0000000000..6eddd2e7b7
--- /dev/null
+++ b/test/erts/fill-string-literal.erts
@@ -0,0 +1,59 @@
+Name: Unfill and fill back string according to current fill-column
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-string-literal))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, '
+ . 'consectetur adipiscing elit. Fusce vel '
+ . 'luctus tellus, n|on varius ante. Nam et '
+ . 'arcu augue.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, n|on varius ante. Nam '
+ . 'et arcu augue.';
+=-=-=
+
+Name: Works if used out side but on the same line of any part of its parts
+=-=
+$stri|ngVar = 'Lorem ipsum dolor sit amet, '
+ . 'consectetur adipiscing elit. Fusce vel '
+ . 'luctus tellus, non varius ante. Nam et '
+ . 'arcu augue.';
+=-=
+$stri|ngVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Nam '
+ . 'et arcu augue.';
+=-=-=
+
+Name: Won't act on code that is inside of another string literal.
+=-=
+$string = "
+ $stringVar = 'Lo|rem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce vel luctus tellus, non varius ante.';
+";
+=-=-=
+
+Name: Refilling will end up readjust the lines when a sufficiently changes
require it
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (insert "lorem ")
+ (php-fill-string-literal))
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur |adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Nam '
+ . 'et arcu augue.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur lorem |'
+ . 'adipiscing elit. Fusce vel '
+ . 'luctus tellus, non varius '
+ . 'ante. Nam et arcu augue.';
+=-=-=
diff --git a/test/erts/newline.erts b/test/erts/newline.erts
new file mode 100644
index 0000000000..d50a609202
--- /dev/null
+++ b/test/erts/newline.erts
@@ -0,0 +1,44 @@
+Name: Splits a string literal into two at point
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (php-fill-newline))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur |adipiscing elit. Fusce
vel luctus tellus, non varius ante.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur '
+ . 'adipiscing elit. Fusce vel luctus tellus, non varius ante.';
+=-=-=
+
+Name: Splits a Phpdoc block's paragraph into two
+=-=
+/**
+ * Lorem ipsum dolor sit amet, consectetur adipiscing elit.| Fusce vel luctus
tellus, non varius ante.
+ */
+=-=
+/**
+ * Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ *
+ *| Fusce vel luctus tellus, non varius ante.
+ */
+=-=-=
+
+Name: Adds an empty line if called at the end of a Phpdoc block's paragraph
+=-=
+/**
+ * Lorem ipsum dolor sit amet, consectetur adipiscing elit.|
+ */
+=-=
+/**
+ * Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ *|
+ */
+=-=-=
+
+Name: Adds an empty new string concatenation string
+=-=
+$stringVar = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.|";
+=-=
+$stringVar = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+ . "|";
+=-=-=
diff --git a/test/erts/refill-mode.erts b/test/erts/refill-mode.erts
new file mode 100644
index 0000000000..ec3e9b2bdb
--- /dev/null
+++ b/test/erts/refill-mode.erts
@@ -0,0 +1,178 @@
+Name: Refills a c style comment when adding text
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c-comments)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c-comments)
+ (php-fill-refill-mode)
+ (ert-simulate-command '(self-insert-command 1 ? ))
+ (insert "descriptio")
+ (ert-simulate-command '(self-insert-command 1 ?n)))
+=-=
+/**
+ * @param string $short Quite long|
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite long
+ * description|
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Refills a c++ style comment when addion text
+=-=
+// Lorem ipsum dolor sit amet,|
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=
+// Lorem ipsum dolor sit amet,
+// description| consectetur adipiscing
+// elit. Fusce vel luctus tellus.
+=-=-=
+
+Name: Refills a string when addion text
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur| adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Nam '
+ . 'et arcu augue.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur description| '
+ . 'adipiscing elit. Fusce vel '
+ . 'luctus tellus, non varius '
+ . 'ante. Nam et arcu augue.';
+=-=-=
+
+Name: Refills a c style comment when deleting text
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c-comments)
+ (custom-reevaluate-setting 'php-fill-nosqueeze-c-comments)
+ (php-fill-refill-mode)
+ (ert-simulate-command '(c-electric-backspace 7)))
+=-=
+/**
+ * @param string $short Quite long
+ * description|
+ * second line
+ * @param array $longName First line,
+ * second line
+ */
+=-=
+/**
+ * @param string $short Quite long
+ * desc second
+ * line
+ * @param array $longName First line,
+ * second line
+ */
+=-=-=
+
+Name: Refills a c++ style comment when deleting text
+=-=
+// Lorem ipsum dolor sit amet,
+// description| consectetur adipiscing
+// elit. Fusce vel luctus tellus.
+=-=
+// Lorem ipsum dolor sit amet, desc|
+// consectetur adipiscing elit. Fusce
+// vel luctus tellus.
+=-=-=
+
+Name: Refills a string when deleting text
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur description| '
+ . 'adipis elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Nam '
+ . 'et arcu augue.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur desc| adipis '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Nam '
+ . 'et arcu augue.';
+=-=-=
+
+Name: Refills only one line up from point
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Na '
+ . 'auguell.| Nulla ac dui auctor, '
+ . 'bibendum dui vitae';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante. Na a| '
+ . 'Nulla ac dui auctor, bibendum '
+ . 'dui vitae';
+=-=-=
+
+Name: Refill is not performed after changes made by command
comment-or-uncomment-region
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-refill-mode)
+ (let ((begx (point-min)) (endx (point-max)))
+ (ert-simulate-command (list 'comment-region begx endx))
+ (ert-simulate-command (list 'uncomment-region begx endx))
+ (ert-simulate-command (list 'comment-or-uncomment-region begx endx))
+ (ert-simulate-command (list 'comment-or-uncomment-region begx endx))))
+=-=
+$stringVar = 'Lo|rem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante.';
+=-=-=
+
+Name: Refill is not performed if php-fill-newline breaks a string literal in
two
+Code: (lambda ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-refill-mode)
+ (ert-simulate-command '(php-fill-newline)))
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur |adipiscing elit. Fusce
vel luctus tellus, non varius ante.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur '
+ . 'adipiscing elit. Fusce vel luctus tellus, non varius ante.';
+=-=-=
+
+Name: Refill is performed when php-fill-newline breaks a Phpdoc block's
paragraphs in two
+=-=
+/**
+ * Lorem ipsum dolor sit amet,
+ * consectetur adipiscing elit. Fusce
+ * vel luctus tellus, non varius
+ * ante. Nam et arcu augue. Nulla ac
+ * dui auctor, bibendum dui vitae,
+ * suscipit sapien.| In porta ante id
+ * metus placerat viverra. Aliquam a
+ * massa eu ante tempus semper. Nullam
+ * ac eros gravida, viverra ipsum eu,
+ * egestas dolor.
+ */
+=-=
+/**
+ * Lorem ipsum dolor sit amet,
+ * consectetur adipiscing elit. Fusce
+ * vel luctus tellus, non varius
+ * ante. Nam et arcu augue. Nulla ac
+ * dui auctor, bibendum dui vitae,
+ * suscipit sapien.
+ *
+ * In porta ante id metus placerat
+ * viverra. Aliquam a massa eu ante
+ * tempus semper. Nullam ac eros
+ * gravida, viverra ipsum eu, egestas
+ * dolor.
+ */
+=-=-=
diff --git a/test/erts/set-local-variables.erts
b/test/erts/set-local-variables.erts
new file mode 100644
index 0000000000..0afa33573f
--- /dev/null
+++ b/test/erts/set-local-variables.erts
@@ -0,0 +1,17 @@
+Name: Sets local values for fill-column and sentence-end-double-space using
variables php-fill-fill-column and php-fill-sentence-end-double-space
respectably
+Code: (lambda ()
+ (custom-reevaluate-setting 'php-fill-fill-column)
+ (custom-reevaluate-setting 'php-fill-sentence-end-double-space)
+ (php-fill-set-local-variables)
+ (should (equal fill-column 80))
+ (should (equal sentence-end-double-space nil)))
+=-=-=
+
+Name: Values other than the default ones might be used on variables
php-fill-fill-column and php-fill-sentence-end-double-space respectably
+Code: (lambda ()
+ (customize-set-variable php-fill-fill-column 120)
+ (customize-set-variable php-fill-sentence-end-double-space t)
+ (php-fill-set-local-variables)
+ (should (equal fill-column 120))
+ (should (equal sentence-end-double-space t)))
+=-=-=
diff --git a/test/erts/stitch-string-parts-together.erts
b/test/erts/stitch-string-parts-together.erts
new file mode 100644
index 0000000000..8c58d06466
--- /dev/null
+++ b/test/erts/stitch-string-parts-together.erts
@@ -0,0 +1,96 @@
+Name: Stitch string parts into one, while point is within one of its parts
+Point-Char: |
+Code: (lambda ()
+ (php-mode)
+ (php-fill-stitch-string-parts-together))
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fu|sce vel luctus '
+ . 'tellus, non varius ante.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fu|sce
vel luctus tellus, non varius ante.';
+=-=-=
+
+Name: Stitch string parts into one, even if not within one, but within a line
containing one
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ | . 'amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante.';
+=-=
+$stringVar = 'Lorem ipsum dolor sit |amet, consectetur adipiscing elit. Fusce
vel luctus tellus, non varius ante.';
+=-=-=
+
+Name: Quote type double can be use as well
+=-=
+$stringVar = "Lorem ipsum dolor sit "
+ . "amet, consectetur adipiscing "
+ . "elit. Fusce vel luctus "
+ . "tellus, n|on varius ante.";
+=-=
+$stringVar = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
vel luctus tellus, n|on varius ante.";
+=-=-=
+
+Name: Two string literals are considered part of the same string only if the
previus string literal ends on a space
+=-=
+$stringVar = 'Lor|em ipsum dolor sit '
+ . 'amet, consectetur adipiscing'
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante.';
+=-=
+$stringVar = 'Lor|em ipsum dolor sit amet, consectetur adipiscing'
+ . 'elit. Fusce vel luctus '
+ . 'tellus, non varius ante.';
+=-=-=
+
+Name: Can't be fool into assuming two lines can be concatenated
+=-=
+ . "tellus, non varius ante "
+$stringVar = "Lo|rem ipsum dolor sit "
+ . "amet, consectetur adipiscing "
+=-=
+ . "tellus, non varius ante "
+$stringVar = "Lo|rem ipsum dolor sit amet, consectetur adipiscing "
+=-=-=
+
+Name: Two string literals are considered part of the same if they share the
same quote type
+=-=
+$stringVar = "Lor|em ipsum dolor sit "
+ . "amet, consectetur adipiscing "
+ . 'elit. Fusce vel luctus '
+ . "tellus, non varius ante.";
+=-=
+$stringVar = "Lor|em ipsum dolor sit amet, consectetur adipiscing "
+ . 'elit. Fusce vel luctus '
+ . "tellus, non varius ante.";
+=-=-=
+
+Name: Strings being concatenated are only stitch together when the subsequent
concatanation string cover the entire line.
+=-=
+$stringVar = 'Lor|em ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fusce ' . 'vel luctus '
+ . 'tellus, non varius ante.';
+=-=
+$stringVar = 'Lor|em ipsum dolor sit amet, consectetur adipiscing '
+ . 'elit. Fusce ' . 'vel luctus '
+ . 'tellus, non varius ante.';
+=-=-=
+
+Name: If a non nil value is given argument ONLY-ONE-LINE-UP only one line up
will be stitch together but every thing else is.
+Code: (lambda ()
+ (php-mode)
+ (php-fill-stitch-string-parts-together t))
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus '
+ . 'tellus, n|on varius ante. Nam '
+ . 'et arcu augue. Nulla ac dui '
+ . 'auctor, bibendum dui vitae';
+=-=
+$stringVar = 'Lorem ipsum dolor sit '
+ . 'amet, consectetur adipiscing '
+ . 'elit. Fusce vel luctus tellus, n|on varius ante. Nam et arcu augue.
Nulla ac dui auctor, bibendum dui vitae';
+=-=-=
diff --git a/test/php-fill-test.el b/test/php-fill-test.el
new file mode 100644
index 0000000000..470d8bd44e
--- /dev/null
+++ b/test/php-fill-test.el
@@ -0,0 +1,106 @@
+;;; php-fill-test.el --- Tests for php-fill
+
+
+;;; Code Preparation Before Tests:
+
+(defvar php-fill-project-root
+ (if (file-exists-p "erts/")
+ (expand-file-name "../") ;; ERT's native cmds are being used
+ default-directory) ;; eask is being used
+ "Establishes what's the project's root dierecory.
+
+It's later used as the base for the location of the ERTS files.
+Depending how ERT is run, either by using ‘eask’ or its native
+way (either the interactive or batch mode), `defult-directory' may show
+the root directory or the same directory where the tests resign (which
+in the context of this project) is the ‘test’ directory. To find which
+is the case, this code checks the existence of the ‘erts’ directory that
+only exist on the ‘test’ directory.")
+
+;; This is only needed by ERT's native commands but not by eask
+(when (not (boundp 'php-fill))
+ (add-to-list 'load-path php-fill-project-root))
+
+;; The following code is only needed by ERT's native batch mode,
+;; otherwise an evaluation has to be run first, but this code will avoid
+;; needed to do so. It's important to mention though, that
+;; independently of whether the interactive or the batch mode is used,
+;; the package ‘php-mode’ must have already been installed. In the case
+;; of eask, it's needed to be installed by using the 'eask install-deps
+;; --dev' command first. Though this function might help eask, it's not
+;; the eask intended way.
+(when (not (boundp 'php-mode))
+ (let (php-mode-location)
+ (when (setq php-mode-location
+ (directory-files "~/.emacs.d/elpa/" t "php-mode-.*"))
+ (add-to-list 'load-path (car php-mode-location)))))
+
+(require 'php-fill)
+(require 'php-mode)
+(require 'ert-x)
+
+(defvar php-fill-erts-dir (concat php-fill-project-root "test/erts/")
+ "Path of the directory that holds the ERTS files.")
+
+(defun php-fill-erts-path (erts-file)
+ "Concatenates `php-fill-erts-dir' with ERTS-FILE."
+ (concat php-fill-erts-dir erts-file))
+
+;; Tests Start Here:
+
+(ert-deftest php-fill-break-long-string-literl-apart ()
+ (ert-test-erts-file (php-fill-erts-path
+ "break-long-string-literl-apart.erts")))
+
+(ert-deftest php-fill-stitch-string-parts-together ()
+ (ert-test-erts-file (php-fill-erts-path
+ "stitch-string-parts-together.erts")))
+
+(ert-deftest php-fill-string-literal ()
+ (ert-test-erts-file (php-fill-erts-path "fill-string-literal.erts")))
+
+(ert-deftest php-fill-c-fill-paragraph-nosqueez ()
+ (ert-test-erts-file (php-fill-erts-path
+ "c-fill-paragraph-nosqueez.erts")))
+
+(ert-deftest php-fill-c-fill-paragraph ()
+ (ert-test-erts-file (php-fill-erts-path "c-fill-paragraph.erts")))
+
+(ert-deftest php-fill-paragraph ()
+ (ert-test-erts-file (php-fill-erts-path "fill-paragraph.erts")))
+
+(ert-deftest php-fill-newline ()
+ (ert-test-erts-file (php-fill-erts-path "newline.erts")))
+
+(ert-deftest php-fill-backward-delete ()
+ (ert-test-erts-file (php-fill-erts-path "backward-delete.erts")))
+
+(ert-deftest php-fill-delete-forward ()
+ (ert-test-erts-file (php-fill-erts-path "delete-forward.erts")))
+
+(ert-deftest php-fill-refill-mode ()
+ (ert-test-erts-file (php-fill-erts-path "refill-mode.erts")))
+
+(ert-deftest php-fill-set-local-variables ()
+ (ert-test-erts-file (php-fill-erts-path "set-local-variables.erts")))
+
+(ert-deftest php-fill-refill-mode-not-while-undo ()
+ "Test that a refill is not performed after \\[undo].
+
+This test could't be run on an erts file because they have their undo
+ring is disabled."
+ (ert-with-test-buffer ()
+ (php-mode)
+ (setq-local fill-column 38)
+ (php-fill-refill-mode)
+ (let ((content "$stringVar = 'Lorem ipsum dolor sit amet, \
+consectetur adipiscing elit. Fusce vel luctus tellus, non varius ante.';"))
+ (insert content)
+ (undo-boundary)
+ (goto-char 17)
+ (ert-simulate-command '(self-insert-command 1 ?n))
+ (undo-boundary)
+ (ert-simulate-command '(undo))
+ (should (equal (buffer-string) content)))))
+
+;;; php-fill-test.el ends here