(setq eshell-history-size 5000)
#+end_src
+** [[https://codeberg.org/akib/emacs-eat/][eat]]
+[2024-02-05 Mon 12:10]
+
+#+begin_src elisp
+ (add-hook 'eshell-load-hook #'eat-eshell-mode)
+ (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode)
+#+end_src
+
** Most of this stolen from the great [[https://github.com/howardabrams/hamacs/blob/main/ha-eshell.org][Howard Abrams]]!
[2022-12-08 Thu 17:43]
--- /dev/null
+Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasignNOSPAMelpa.gnu.org> (trust undefined) created at 2023-12-15T23:10:04+0100 using RSA
+Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasignNOSPAMelpa.gnu.org> (trust undefined) created at 2023-12-15T23:10:04+0100 using EDDSA
\ No newline at end of file
--- /dev/null
+;;; Directory Local Variables -*- no-byte-compile: t -*-
+;;; For more information see (info "(emacs) Directory Variables")
+
+((nil . ((fill-column . 70)
+ (indent-tabs-mode . nil)))
+ (sh-mode . ((sh-basic-offset . 2)))
+ (makefile-mode . ((indent-tabs-mode . t)))
+ (".git" . ((text-mode . ((fill-column . 63))))))
--- /dev/null
+CONTRIBUTE
+Makefile
+eat-tests.el
+gitlog-to-changelog
+make-changelog
+texinfo.tex
--- /dev/null
+ 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>.
--- /dev/null
+2023-12-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't let automatic scrolling mess up the display
+
+ * eat.el (eat-mode, eat--eshell-local-mode): Set both
+ 'scroll-margin' and 'hscroll-margin' to zero.
+
+2023-10-26 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't queue input
+
+ * eat.el (eat--pending-input-chunks)
+ (eat--defer-input-processing, eat--process-input-queue-timer):
+ Remove.
+ All references updated.
+ * eat.el (eat--send-input): Send the input immediately.
+ * eat.el (eat--process-input-queue): Remove.
+ * eat.el (eat--eshell-process-output-queue)
+ (eat--process-output-queue): Loop while output queue isn't
+ empty, set 'eat--output-queue-first-chunk-time' to 't' in the
+ loop.
+ * eat.el (eat--filter, eat--eshell-filter): Don't start a timer
+ if 'eat--output-queue-first-chunk-time' is 't'.
+
+2023-10-19 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.ti (eat-mono): Remove unused capability 'Ed'
+
+2023-10-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix input processing & auto line mode
+
+ * eat.el (eat--process-input-queue): Set
+ 'eat--process-input-queue-timer' to 'nil'.
+ * eat.el (eat--auto-line-mode-pending-toggles): New variable.
+ * eat.el (eat--line-mode-enter-auto-1): Don't take any
+ argument.
+ * eat.el (eat--line-mode-exit-auto-1): Don't take any argument.
+ Don't call 'eat-line-mode'.
+ * eat.el (eat--line-mode-enter-auto, eat--line-mode-exit-auto):
+ Queue the toggle in 'eat--auto-line-mode-pending-toggles'
+ instead of starting a timer.
+ * eat.el (eat--line-mode-do-toggles): New function.
+ * eat.el (eat--process-output-queue): Let-bind
+ 'eat--auto-line-mode-pending-toggles' to nil. Call
+ 'eat--line-mode-do-toggles'.
+
+2023-10-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix compiler warnings
+
+ * eat.el: Wrap all 'emacs-major-version' checks with
+ 'eval-when-compile'.
+ * eat.el (eat--process-input-queue): Don't use obsolete
+ generalized variable 'buffer-local-value'.
+
+2023-10-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't let 'eat--process-input-queue' to recurse
+
+ * eat.el (eat--defer-input-processing): New variable.
+ * eat.el (eat-mode, eat--eshell-local-mode): Make
+ 'eat--defer-input-processing' buffer-local.
+ * eat.el (eat--process-input-queue): If
+ 'eat--defer-input-processing' is non-nil, do nothing, otherwise
+ bind it to non-nil while sending input.
+
+2023-10-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't mess up terminal when switching to line mode
+
+ * eat.el (eat--line-mode-enter-auto-1)
+ (eat--line-mode-exit-auto-1): New function.
+ * eat.el (eat--line-mode-enter-auto, eat--line-mode-exit-auto):
+ Do everything after the output is processed.
+
+2023-10-10 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't flicker due to screen line breaking
+
+ * eat.el (eat--eshell-synchronize-scroll)
+ (eat--synchronize-scroll): Use 'recenter' instead of
+ 'set-window-start' to synchronize scrolling.
+
+2023-10-10 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix side-effect in 'eat--set-term-sixel-params'
+
+ * eat.el (eat--set-term-sixel-params): Fix unintended
+ side-effect.
+
+2023-10-10 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix 'eat--set-term-sixel-params' on text display
+
+ * eat.el (eat--set-term-sixel-params): Don't error on text
+ display.
+
+2023-10-09 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix 'eat--eshell-set-input-process' advice
+
+ * eat.el (eat--eshell-set-input-process): Take any number of
+ arguments and ignore them.
+
+2023-10-09 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Make motion commands work properly
+
+ * eat.el (eat--line-mode): Set 'front-sticky' and
+ 'rear-nonsticky' text properties to 't' when enabling mode, and
+ revert them when disabling.
+ * eat.el (eat--process-output-queue): Don't add 'front-sticky'
+ and 'rear-nonsticky' text properties if not in line mode.
+ * eat.el (eat--sentinel): Don't remove 'front-sticky' and
+ 'rear-nonsticky' text properties, they shouldn't be in the
+ buffer.
+
+2023-10-09 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Remove internal text properties when killing text
+
+ * eat.el (eat-term-filter-string): Remove 'read-only',
+ 'rear-nonsticky', 'front-sticky' and 'field' text properties.
+ * eat.el (eat--filter-buffer-substring): Remove
+ 'eat--t-char-width', 'eat--t-sixel-bitmap-size' and
+ 'eat--t-sixel-bitmap' text properties.
+
+2023-10-08 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix Makefile
+
+ * Makefile (eat.elc, check): Pass $(EMACSFLAGS) to $(EMACS).
+
+2023-10-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix garbage image after the end of Sixel image
+
+ * eat.el (eat--t-sixel-init): Increase Sixel buffer size.
+
+2023-10-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support Emacs 26.1
+
+ * eat.el: Depend on Emacs 26.1.
+ * eat.el (eat--t-handle-output, eat--handle-uic)
+ (eat--eshell-handle-uic): Don't use '(not CHAR)' form in 'rx'
+ forms.
+ * eat.el (eat--eshell-process-output-queue): Use
+ 'combine-change-calls' if available.
+ * README.org: Update to reflect support for Emacs 26.
+
+2023-10-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Update tests to make them pass
+
+ * eat-tests.el: Use 'eat-term-parameter'.
+ * eat-tests.el (eat-test-set-cwd): Test OSC 7 only.
+
+2023-10-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Modify eshell-variable-aliases-list buffer-locally
+
+ * eat.el (eat-eshell-mode): Don't modify
+ 'eshell-variable-aliases-list'.
+ * eat.el (eat--eshell-local-mode): Modify
+ 'eshell-variable-aliases-list'.
+
+2023-10-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support Emacs 27.1
+
+ * eat.el: Depend on Emacs 27.1. Require 'compat' and 'term'.
+ * eat.el (eat-term-color-*): Inherit 'term-color-*' in Emacs
+ 27.
+ * eat.el (eat--t-sixel-render-bitmap): Call 'mapconcat' with
+ three arguments.
+ * eat.el (eat-yank-from-kill-ring): Signal error in Emacs 27.
+ * eat.el (eat--eshell-setup-proc-and-term): Don't error if
+ process mark is invalid.
+ * eat.el (eat-eshell-mode): Properly revert
+ 'eshell-variable-aliases-list' when disabling the mode.
+ * eat.el (eat--trace-exec)
+ (eat--trace-eshell-adjust-make-process-args): Make sure
+ 'lisp-data-mode' is defined before calling.
+
+2023-10-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Enable shell command completion by default
+
+ * eat.el (eat-mode): Use shell mode's completion facilities.
+
+2023-10-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't put overlay on prompt while history Isearch
+
+ * eat.el (eat--line-history-isearch-message-overlay)
+ (eat--line-history-isearch-message): Remove.
+ * eat.el (eat--line-history-isearch-setup)
+ (eat--line-history-isearch-end): Don't modify
+ 'isearch-message-function'.
+ * eat.el (eat-mode): Don't make 'isearch-message-function' and
+ 'eat--line-history-isearch-message-overlay' buffer-local.
+
+2023-10-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Put the cursor below Sixel image after showing it
+
+ * eat.el (eat--t-sixel-cleanup): Make sure the cursor is below
+ the image.
+
+2023-10-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Apply scaling and ascept ratio on Sixel properly
+
+ * eat.el (eat--set-term-sixel-params): Make sure both numbers
+ of char-dimension is non-zero.
+
+2023-10-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use terminal parameters to set callback functions
+
+ Also make sure the terminal passed as arguments to API
+ functions is live.
+
+ * eat.el (eat--t-term): Update default value of slot 'params'.
+ * eat.el (eat-term-p, eat-term-live-p): New function.
+ * eat.el (eat--t-ensure-live-term): New macro.
+ * eat.el (eat--t-with-env, eat-term-parameter, eat-term-size)
+ (eat-term-set-parameter, eat-term-cursor-type, eat-term-end)
+ (eat-term-beginning, eat-term-display-cursor, eat-term-title)
+ (eat-term-in-alternative-display-p, eat-term-input-event)
+ (eat-term-send-string, eat-term-send-string-as-yank): Ensure
+ the terminal passed as argument is live.
+ * eat.el (eat-term-delete): Ensure the terminal passed as
+ argument is live. Mark terminal as deleted.
+ * eat.el (eat-term-parameters): New function.
+ * eat.el (eat-term-set-parameter): Handle more special
+ parameters: 'input-function', 'ring-bell-function',
+ 'grab-mouse-function', 'grab-focus-events-function',
+ 'manipulate-selection-function', 'set-title-function' and
+ 'set-cwd-function'.
+ * eat.el (eat-term-input-function, eat-term-ring-bell-function)
+ (eat-term-set-cursor-function, eat-term-grab-mouse-function)
+ (eat-term-grab-focus-events-function)
+ (eat-term-manipulate-selection-function)
+ (eat-term-set-title-function, eat-term-set-cwd-function):
+ Remove function.
+ * eat.el (eat-exec, eat--eshell-setup-proc-and-term)
+ (eat--trace-replay-eval): Update to use parameters.
+
+2023-10-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support rendering Sixel with XPM images
+
+ * eat.el (eat--t-sixel-render-bitmap): Support conversion to
+ XPM format.
+ * eat.el (eat-sixel-render-formats): Add XPM to the default.
+ * eat.el (eat-term-set-parameter, eat--sixel-render-format):
+ Support XPM as an allowed format.
+ * eat.texi (Sixel): Update.
+
+2023-10-03 Akib Azmain Turja <akib@disroot.org>
+
+ Refactor 'eat--t-sixel-flush-line'
+
+ * eat.el (eat--t-sixel-render-bitmap): New function.
+ * eat.el (eat--t-sixel-flush-line): Move bitmap rendering code
+ to 'eat--t-sixel-render-bitmap'.
+
+2023-10-02 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat-enable-alternative-display): Obsolete
+
+2023-10-02 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Allow customizing Sixel scaling and aspect ratio
+
+ * eat.el (eat-sixel-scale, eat-sixel-aspect-ratio): New user
+ option.
+ * eat.el (eat--t-term): Remove slot 'sixel-image-height'. New
+ slot 'sixel-image-extra-props'.
+ * eat.el (eat--t-sixel-flush-line): Give more control to the UI
+ on the image properties.
+ * eat.el (eat-term-set-parameter): Don't treat parameter
+ 'sixel-image-height' specially. Treat parameter
+ 'sixel-image-extra-properties' specially.
+ * eat.el (eat--set-term-sixel-params): New function.
+ * eat.el (eat-exec, eat--eshell-setup-proc-and-term): Set Sixel
+ related terminal parameters with 'eat--set-term-sixel-params'.
+ * eat.texi (Sixel): Document 'eat-sixel-scale' and
+ 'eat-sixel-aspect-ratio'.
+
+2023-09-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support <backtab>
+
+ * eat.el (eat-term-input-event): Handle '<tab>' and '<backtab>'
+ events.
+ * eat.el (eat-term-make-keymap): Bind '<tab>' and '<backtab>'.
+ * eat.ti (eat-mono): Add 'kcbt' capability.
+
+2023-09-27 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Handle output correctly in emacs mode in Eshell
+
+ * eat.el (eat--eshell-output-filter): Inhibit read only.
+
+2023-09-24 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add command 'eat-send-password'
+
+ * eat.el (eat-send-password): New command.
+ * eat.texi (Password Input): New chapter.
+
+2023-09-24 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add the underlying terminal object to public API
+
+ * eat.el (eat--terminal): Rename to 'eat-terminal'.
+ All references changed.
+
+2023-09-23 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ New command eat-line-load-input-history-from-file
+
+ * eat.el (eat-line-load-input-history-from-file): New command.
+
+2023-09-23 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Integrate Isearch with line mode input history
+
+ * eat.el (eat-line-input-history-isearch): New user option.
+ * eat.el (eat-line-mode-map): Bind 'M-r' to
+ 'eat-line-history-isearch-backward-regexp'.
+ * eat.el (eat-line-mode): Error if process isn't running.
+ * eat.el (eat--line-history-isearch-message-overlay)
+ (eat--saved-line-input-history-isearch): New variable.
+ * eat.el (eat--line-delete-input): Remove.
+ All callers changed.
+ * eat.el (eat-line-history-isearch-backward-regexp)
+ (eat-line-history-isearch-backward): New command.
+ * eat.el (eat--line-history-isearch-setup)
+ (eat--line-history-isearch-end, eat--line-history-isearch-wrap)
+ (eat--line-history-isearch-search, eat--line-goto-input)
+ (eat--line-history-isearch-message)
+ (eat--line-history-isearch-push-state)
+ (eat--line-history-isearch-pop-state): New function.
+ * eat.el (eat-mode): Make
+ 'eat--line-history-isearch-message-overlay',
+ 'isearch-search-fun-function', 'isearch-message-function',
+ 'isearch-wrap-function' and 'isearch-push-state-function'
+ buffer-local. Add 'eat--line-history-isearch-setup' to
+ 'isearch-mode-hook' locally.
+ * eat.texi (Line Mode): Document this new feature.
+
+2023-09-23 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Move to the input line automatically in line mode
+
+ * eat.el (eat-line-auto-move-to-input): New user option.
+ * eat.el (eat--line-move-to-input): New function.
+ * eat.el (eat--line-mode): Add/remove 'eat--line-move-to-input'
+ to 'pre-command-hook' locally.
+ * eat.texi (Line Mode): Document 'eat-line-auto-move-to-input'.
+
+2023-09-23 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Rename prompt mode to line mode and generalize it
+
+ * eat.el: Rename prompt mode to line mode, also rename related
+ symbols to have 'eat-line-' or 'eat--line-' prefix.
+ * eat.el (eat-enable-native-shell-prompt-editing): Rename to
+ 'eat-enable-auto-line-mode'.
+ * eat.el (eat--line-mode-enter-auto)
+ (eat--line-mode-exit-auto): New function.
+ * eat.el (eat--post-prompt, eat--post-cont-prompt): Call
+ 'eat--line-mode-enter-auto' to enter line mode.
+ * eat.el (eat--pre-cmd): Call 'eat--line-mode-exit-auto'.
+ * eat.el (eat--get-shell-history): Populate input ring
+ unconditionally.
+ * eat.el (eat-emacs-mode, eat-semi-char-mode, eat-char-mode):
+ Call 'eat--line-mode-exit' to exit line mode.
+ * eat.el (eat--line-mode): Move all logic to 'eat-line-mode',
+ 'eat--line-mode-exit' and 'eat--line-mode-exit-auto'.
+ * eat.el (eat-line-send): Make non-interactive. Reset input
+ history cycling variables.
+ * eat.el (eat-line-send-input): New argument NO-NEWLINE.
+ * eat.el (eat-mode): Don't disable undo information recording.
+ * eat.el (eat--process-output-queue): Disable undo information
+ recording while process output.
+ * eat.texi (Line Mode): New section in chapter 'Input Modes'.
+ * eat.texi (Line Mode Integration): New section in chapter
+ 'Shell Integration'.
+ * eat.texi (Native Shell Prompt Editing): Remove section.
+ * README.org (Usage): Avoid the term "keybinding mode", use
+ "input mode" instead as the manual uses it. Document line
+ mode.
+ * README.org (NonGNU ELPA): Emacs 28 has NonGNU ELPA enabled by
+ default, so remove unnecessary instructions.
+
+2023-09-22 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Skip comments in Bash history file
+
+ * eat.el (eat--prompt-populate-input-ring): Skip Bash history
+ comments.
+ * eat.el: Add Compat as dependency; some functions from Emacs
+ 29 are used.
+
+2023-09-18 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Allow customizing Sixel rendering format
+
+ * eat.el (eat-sixel-render-formats): New user option.
+ * eat.el (eat-eshell-fallback-if-stty-not-available): Fix
+ customization type.
+ * eat.el (eat--t-term): Rename slot 'sixel-display-method' to
+ 'sixel-render-format'.
+ All callers changed.
+ * eat.el (eat--t-sixel-flush-line): New support render format,
+ 'none'.
+ * eat.el (eat-term-set-parameter): Rename parameter
+ 'sixel-display-method' to 'sixel-render-format'.
+ All callers changed.
+ * eat.el (eat--sixel-render-format): New function.
+ * eat.el (eat-exec, eat--eshell-setup-proc-and-term): Set
+ 'sixel-render-format' according to user customization.
+
+2023-09-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add message passing support
+
+ * eat.el (eat-message-handler-alist): New user option.
+ * eat.el (eat--handle-message): New function.
+ * eat.el (eat--handle-uic, eat--eshell-handle-uic): Handle
+ message passing sequence.
+ * eat.texi (Message Passing): New section in chapter "Shell
+ Integration".
+ * integration/bash (__eat_enable_integration): Remove the
+ unnecessary complex code to update PROMPT_COMMAND.
+ * integration/bash (_eat_msg):
+ * integration/zsh (_eat_msg):
+ New function.
+
+2023-09-16 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't enter prompt mode after exit till new prompt
+
+ * eat.el (eat--inhibit-prompt-mode): New variable.
+ * eat.el (eat--post-prompt, eat--post-cont-prompt): Check
+ 'eat--inhibit-prompt-mode' before switching to prompt mode.
+ * eat.el (eat--before-new-prompt): New function.
+ * eat.el (eat--handle-uic): Support "before new prompt"
+ sequence.
+ * eat.el (eat-emacs-mode, eat-semi-char-mode, eat-char-mode):
+ Set 'eat--inhibit-prompt-mode' to t if prompt mode is enabled.
+ * eat.el (eat-mode): Make 'eat--inhibit-prompt-mode'
+ buffer-local.
+ * integration/bash (__eat_prompt_command):
+ * integration/zsh (__eat_precmd):
+ Send the "before new prompt" sequence.
+
+2023-09-16 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add history reporting in Zsh integration script
+
+ * eat.el (eat--get-shell-history): New argument FORMAT, pass it
+ to 'eat--prompt-populate-input-ring'.
+ * eat.el (eat--handle-uic): Accept FORMAT argument in input
+ history reporting sequence and pass it to
+ 'eat--get-shell-history'.
+ * eat.el (eat--prompt-populate-input-ring): New argument
+ FORMAT. Support Zsh extended history file format.
+ * integration/bash (__eat_enable_integration): Send "bash" as
+ the history file format.
+ * integration/zsh (__eat_enable_integration): Send shell
+ history.
+
+2023-09-16 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix input handling in Eshell
+
+ * eat.el (eat--eshell-local-mode): Make input processing
+ variables buffer-local.
+
+2023-09-14 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat-prompt-newline): Make ring if needed
+
+2023-09-14 Illia Ostapyshyn <ilya.ostapyshynNOSPAMgmail.com>
+
+ * eat.el (eat-mode): Escape '%' character in title
+
+2023-09-14 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix recursive output processing
+
+ * eat.el (eat--pending-input-chunks)
+ (eat--process-input-queue-timer): New variable.
+ * eat.el (eat-mode): Make 'eat--pending-input-chunks' and
+ 'eat--process-input-queue-timer' buffer-local.
+ * eat.el (eat--send-input): Queue input instead of sending
+ immediately.
+ * eat.el (eat--process-input-queue): New function.
+
+2023-09-14 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Document prompt mode
+
+ * eat.texi (Shell Integration): Divide into sections. Add new
+ section 'Native Shell Prompt Editing'.
+ * README.org (Usage): Document "prompt" mode.
+ * README.org (Comparison With Other Terminal Emulators): Update
+ comparison.
+
+2023-09-14 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Allow terminal text modification after it's killed
+
+ * eat.el (eat--sentinel): Remove 'read-only' and other text
+ properties from the terminal region.
+
+2023-09-13 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix Bash long startup when run from Eshell
+
+ * eat.el (eat--eshell-handle-uic): Acknowledge when input
+ history file is sent by the shell.
+
+2023-09-13 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Disable native shell prompt editing by default
+
+ * eat.el (eat-enable-native-shell-prompt-editing): Set to nil.
+
+2023-09-13 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add prompt mode and process OSC 51 as UI Command
+
+ * eat.el (eat-enable-native-shell-prompt-editing)
+ (eat-prompt-input-ring-size)
+ (eat-prompt-move-point-for-matching-input): New user option.
+ * eat.el (eat--t-term): Remove slots 'cwd', 'prompt-start-fn',
+ 'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
+ 'cmd-start-fn' and 'cmd-finish-fn'. Add new slot 'ui-cmd-fn'.
+ * eat.el (eat--t-set-cwd): Support only the format used by OSC
+ 7.
+ * eat.el (eat--t-prompt-start, eat--t-prompt-end)
+ (eat--t-cont-prompt-start, eat--t-cont-prompt-end)
+ (eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): Remove
+ function.
+ * eat.el (eat--t-ui-cmd): New function.
+ * eat.el (eat--t-handle-output): Remove all specialized OSC 51
+ handlers and call 'eat--t-ui-cmd' to handle any OSC 51
+ sequence.
+ * eat.el (eat-term-set-parameter): Set 'ui-cmd-fn' slot of
+ terminal when 'ui-command-function' is set.
+ * eat.el (eat-term-cwd): Remove function.
+ * eat.el (eat-term-prompt-start-function)
+ (eat-term-prompt-end-function, eat-term-cmd-start-function)
+ (eat-term-cont-prompt-start-function)
+ (eat-term-cont-prompt-end-function, eat-term-set-cmd-function)
+ (eat-term-cmd-finish-function): Remove generalized variables.
+ * eat.el (eat-term-send-string): New function.
+ * eat.el (eat-send-string-as-yank): Rename to
+ 'eat-term-send-string-as-yank'.
+ All callers changed.
+ * eat.el (eat--set-cwd-uic, eat--post-cont-prompt): New
+ function.
+ * eat.el (eat--pre-prompt, eat--post-prompt, eat--set-cmd)
+ (eat--pre-cmd, eat--set-cmd-status): Remove unused first
+ argument.
+ All callers changed.
+ * eat.el (eat--get-shell-history, eat--handle-uic): New
+ function.
+ * eat.el (eat-prompt-mode-map): New variable.
+ * eat.el (eat-emacs-mode, eat-semi-char-mode, eat-char-mode):
+ Handle the case when prompt mode is active.
+ * eat.el (eat--prompt-mode-previous-mode): New variable.
+ * eat.el (eat--prompt-mode): New non-interactive minor mode.
+ * eat.el (eat-prompt-send-default, eat-prompt-send)
+ (eat-prompt-newline, eat-prompt-delchar-or-eof)
+ (eat-prompt-send-interrupt): New command.
+ * eat.el (eat--prompt-input-ring, eat--prompt-input-ring-index)
+ (eat--prompt-stored-incomplete-input)
+ (eat--prompt-matching-input-from-input-string): New variable.
+ * eat.el (eat--prompt-populate-input-ring)
+ (eat--prompt-reset-input-ring-vars, eat--prompt-ask-for-regexp-arg)
+ (eat--prompt-search-arg, eat--prompt-search-start)
+ (eat--prompt-prev-input-string, eat--prompt-prev-matching-input-str)
+ (eat--prompt-delete-input, eat--prompt-prev-matching-input-str-pos):
+ New function.
+ * eat.el (eat-prompt-previous-input, eat-prompt-next-input)
+ (eat-prompt-restore-input, eat-prompt-previous-matching-input)
+ (eat-prompt-next-matching-input, eat-prompt-find-input)
+ (eat-prompt-previous-matching-input-from-input)
+ (eat-prompt-next-matching-input-from-input): New command.
+ * eat.el (eat-mode): Make 'eat--prompt-mode-previous-mode',
+ 'eat--prompt-input-ring', 'eat--prompt-input-ring-index',
+ 'eat--prompt-stored-incomplete-input' and
+ 'eat--prompt-matching-input-from-input-string' buffer-local.
+ Record undo information if
+ 'eat-enable-native-shell-prompt-editing' is enabled. Set
+ 'mode-line-process' properly so that prompt mode is shown when
+ enabled.
+ * eat.el (eat--process-output-queue): Remove any narrowing
+ temporarily when called. Don't
+ * eat.el (eat--sentinel): Disable prompt mode. Also fix the
+ bug where the point centers when the program exits, instead of
+ going to the end of buffer.
+ * eat.el (eat-exec): Don't set removed generalized variables
+ 'eat-term-prompt-start-function', 'eat-term-set-cmd-function',
+ 'eat-term-prompt-end-function', 'eat-term-cmd-start-function'
+ and 'eat-term-cmd-finish-function'. Set terminal parameter
+ 'ui-command-function' to 'eat--handle-uic'.
+ * eat.el (eat--eshell-handle-uic): New function.
+ * eat.el (eat--eshell-output-filter): Let-bind
+ 'inhibit-read-only' only for required parts.
+ * eat.el (eat--eshell-setup-proc-and-term): Set terminal
+ parameter 'ui-command-function' to 'eat--eshell-handle-uic'.
+ * eat.el (eat--eshell-sentinel): Fix the bug where the point
+ centers when the program exits, instead of going to the end of
+ buffer.
+ * integration/bash (__eat_enable_integration): Send shell
+ history.
+
+2023-09-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat-project-other-window): New command
+
+2023-08-31 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add command 'eat-other-window'
+
+ * eat.el (eat--1, eat-other-window): New function.
+ * eat.el (eat): Move all logic to 'eat--1' and call it.
+
+2023-08-27 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support Sixel properly in Eshell
+
+ * eat.el (eat--eshell-setup-proc-and-term): Set Sixel
+ attributes of the terminal object.
+
+2023-08-25 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add experimental Sixel support
+
+ * eat.el (eat--t-cur): New slots 'sixel-x', 'sixel-y' and
+ 'sixel-beg'.
+ * eat.el (eat--t-term): New slots 'sixel-buffer',
+ 'sixel-buffer-size', 'sixel-palette', 'sixel-color',
+ 'sixel-display-method', 'sixel-image-height',
+ 'sixel-scroll-mode', 'sixel-initial-cursor-pos', 'char-width'
+ and 'char-height'.
+ * eat.el (eat--t-reset): Reset 'sixel-scroll-mode' to 't'.
+ * eat.el (eat--t-fix-partial-multi-col-char): Preserve original
+ face if PRESERVE-FACE is non-nil.
+ * eat.el (eat--t-send-device-attrs): Send correct attributes.
+ * eat.el (eat--t-report-foreground-color)
+ (eat--t-report-background-color): Use correct format.
+ * eat.el (eat--t-sixel-init, eat--t-send-graphics-attrs)
+ (eat--t-sixel-write, eat--t-sixel-flush-line)
+ (eat--t-sixel-newline, eat--t-sixel-set-color-reg)
+ (eat--t-sixel-cleanup, eat--t-sixel-enable-scrolling)
+ (eat--t-sixel-disable-scrolling): New function.
+ * eat.el (eat--t-set-modes, eat--t-reset-modes): Handle Sixel
+ scroll mode.
+ * eat.el (eat--t-handle-output): Update
+ 'eat--t-send-device-attrs' call. Handle 'send graphics
+ attributes' CSI function. Parse and dispatch DCS sequence
+ properly. Handle Sixel sequence.
+ * eat.el (eat-term-set-parameter): Handle 'char-dimensions',
+ 'sixel-display-method', and 'sixel-image-height' parameters.
+ * eat.el (eat-exec): Set 'char-dimensions',
+ 'sixel-display-method', and 'sixel-image-height' parameters.
+
+2023-07-20 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Implement device status report function properly
+
+ * eat.el (eat--t-device-status-report): Implement properly.
+ Take an argument.
+ * eat.el (eat--t-handle-output): Update call to
+ 'eat--t-device-status-report'.
+
+2023-07-12 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Bind 'S-<insert>' to 'eat-yank'
+
+ * eat.el (eat--eshell-prepare-semi-char-mode-map)
+ (eat--prepare-semi-char-mode-map): Bind 'S-<insert>' to
+ 'eat-yank'.
+
+2023-07-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Bind keys 'DEL' and 'M-DEL' keys
+
+ * eat.el (eat-term-input-event): Handle 'DEL' and 'M-DEL' keys.
+ * eat.el (eat-term-make-keymap): Bind 'DEL' and 'M-DEL' keys.
+
+2023-07-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix recursive load error
+
+ * eat.el (eat-semi-char-non-bound-keys)
+ (eat-eshell-semi-char-non-bound-keys): Let-bind
+ 'after-load-alist' and 'after-load-functions' before reloading
+ Eat.
+
+2023-05-15 Akib Azmain Turja <akib@disroot.org>
+
+ Yank active region with middle-click yank
+
+ * eat.el (eat-mouse-yank-primary): Select active region if
+ 'select-active-regions' is non-nil.
+
+2023-05-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix middle-click yanking commands
+
+ * eat.el (eat-mouse-yank-primary): Switch to the window where
+ the event was initiated.
+ * eat.el (eat-mouse-yank-secondary): Switch to the window where
+ the event was initiated. Ensure that the secondary selection
+ is non-empty before sending it.
+
+2023-05-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support middle-click yank in terminal
+
+ * eat.el (eat-mouse-yank-primary, eat-mouse-yank-secondary):
+ New command.
+ * eat.el (eat--prepare-semi-char-mode-map)
+ (eat--eshell-prepare-semi-char-mode-map): Remap commands
+ 'mouse-yank-primary' and 'mouse-yank-secondary' to
+ 'eat-mouse-yank-primary' and 'eat-mouse-yank-secondary'
+ respectively.
+
+2023-04-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Update documentation in commentary section
+
+ * README.org (Usage): List keybindings in semi-char mode to
+ switch to other keybinding modes.
+ * eat.el (Commentary): Put the documentation of semi-char mode
+ first as it is the default. List keybindings in semi-char mode
+ to switch to other keybinding modes. Update stale keybindings
+ listed in emacs mode documentation.
+
+2023-04-09 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Pass process to eat-exec-hook and eat-exit-hook
+
+ * eat.el (eat-exec-hook, eat-exit-hook): Update docstring.
+ * eat.el (eat--sentinel): Pass process to 'eat-exit-hook'.
+ Delete process after running 'eat-exit-hook'.
+ * eat.el (eat--kill-buffer): New helper function.
+ * eat.el (eat-exec): Pass process to 'eat-exec-hook'. Add or
+ remove 'eat--kill-process' from 'eat-exit-hook' instead of
+ 'kill-buffer'.
+
+2023-04-09 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ New command 'eat-narrow-to-shell-prompt'
+
+ * eat.el (eat--post-prompt): Put the 'eat--shell-prompt-begin'
+ text property at the beginning of shell prompt.
+ * eat.el (eat--correct-shell-prompt-mark-overlays): Don't try
+ to go outside accessible portion of buffer when the buffer is
+ narrowed.
+ * eat.el (eat-narrow-to-shell-prompt): New command.
+ * eat.el (eat-mode-map): Bind key sequence 'C-x n d' to
+ 'eat-narrow-to-shell-prompt'.
+ * eat.el (eat--filter-buffer-substring): Remove all text
+ properties added on UI side before passing buffer substring to
+ 'eat-term-filter-string'.
+ * eat.texi (Shell Integration): Document
+ 'eat-narrow-to-shell-prompt'.
+
+2023-04-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Run hooks on terminal update and process exit
+
+ * eat.el (eat-exit-hook, eat-update-hook, eat-eshell-exit-hook)
+ (eat-eshell-update-hook): New user option.
+ * eat.el (eat-reset, eat--process-output-queue): Run
+ 'eat-update-hook'.
+ * eat.el (eat--sentinel): Don't test 'eat-kill-buffer-on-exit',
+ run 'eat-exit-hook'.
+ * eat.el (eat--adjust-process-window-size): Run
+ 'eat-update-hook' when the major mode is 'eat-mode'. Run
+ 'eat-eshell-update-hook' in 'eshell-mode' buffers.
+ * eat.el (eat-exec): Don't let-bind 'eat-kill-buffer-on-exit'
+ while killing old process, remove 'kill-buffer' from hook
+ 'eat-exit-hook' instead. When 'eat-kill-buffer-on-exit' is
+ non-nil, add 'kill-buffer' to 'eat-exit-hook' with priority 90.
+ Run 'eat-exec-hook' outside any let-block.
+ * eat.el (eat--eshell-output-filter): Run
+ 'eat-eshell-update-hook'.
+ * eat.el (eat--eshell-cleanup): Run 'eat-eshell-exit-hook'.
+
+2023-04-05 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix resizing when alternative display is enabled
+
+ * eat.el (eat--t-term): Fix error while resizing when
+ alternative display is enabled.
+
+2023-04-02 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Force directionality of paragraphs in Eat buffer
+
+ * eat.el (eat-mode): Set 'bidi-paragraph-direction' to
+ 'left-to-right'.
+
+2023-04-02 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Inform about unlisted semi-char mode exceptions
+
+ * eat.texi (Input Modes): Inform about unlisted semi-char mode
+ exceptions.
+ * README.org: Inform about unlisted semi-char mode exceptions.
+ Add Zsh integration instructions.
+
+2023-03-31 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support DECSCUSR control function
+
+ * eat.el (eat-very-visible-vertical-bar-cursor-type)
+ (eat-vertical-bar-cursor-type, eat-horizontal-bar-cursor-type)
+ (eat-very-visible-horizontal-bar-cursor-type): New user
+ options.
+ * eat.el (eat--t-term): New slot 'cur-visible-p'. Remove slot
+ 'cur-blinking-p'. Change the default value of 'cur-state' to
+ ':block'.
+ * eat.el (eat--t-reset): Don't reset slot 'cur-blinking-p'.
+ Reset slot 'cur-visible-p'. Reset 'cur-state' to ':block'.
+ Reset cursor state to ':block'.
+ * eat.el (eat--t-set-cursor-state): Set slot 'cur-visible-p' to
+ the current visibility of cursor. Set slot 'cur-state' to the
+ shape of cursor, regardless of visibility.
+ * eat.el (eat--t-default-cursor): Rename to
+ 'eat--t-show-cursor'. Don't change any cursor state except
+ visibility.
+ * eat.el (eat--t-invisible-cursor): Rename to
+ 'eat--t-hide-cursor'. Don't change any cursor state except
+ visibility.
+ * eat.el (eat--t-set-cursor-style): New function.
+ * eat.el (eat--t-blinking-cursor, eat--t-non-blinking-cursor):
+ Update to handle new cursor shapes properly.
+ * eat.el (eat--t-set-modes): Call 'eat--t-show-cursor' instead
+ of 'eat--t-default-cursor'.
+ * eat.el (eat--t-reset-modes): Call 'eat--t-hide-cursor'
+ instead of 'eat--t-invisible-cursor'.
+ * eat.el (eat--t-handle-output): Handle DECSCUSR control
+ function.
+ * eat.el (eat-term-cursor-type): Return ':invisible' if cursor
+ is invisible, otherwise the value of slot 'cur-state'. Update
+ the list of possible cursor states in the docstring.
+ * eat.el (eat-term-set-cursor-function): Update the list of
+ possible cursor states and fallback cursor state in the
+ docstring.
+ * eat.el (eat--cursor-blink-mode): Add
+ 'eat--cursor-blink-stop-timers' to 'kill-buffer-hook'.
+ * eat.el (eat--set-cursor): Support new cursor states. Update
+ the list of possible cursor states in the docstring.
+ * eat.texi (Cursor Types): Document new user options
+ 'eat-vertical-bar-cursor-type',
+ 'eat-very-visible-vertical-bar-cursor-type',
+ 'eat-horizontal-bar-cursor-type' and
+ 'eat-very-visible-horizontal-bar-cursor-type'.
+
+2023-03-31 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Capture keys 'M-backspace' and 'C-M-backspace'
+
+ * eat.el (eat-term-input-event): Support 'M-backspace' and
+ 'C-M-backspace'.
+ * eat.el (eat-term-make-keymap): Bind 'M-backspace' and
+ 'C-M-backspace'.
+
+2023-03-31 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Suggest to invoke 'eat-compile-terminfo' in manual
+
+ * eat.texi (Not Recognized, Garbled Text): Suggest to do
+ 'M-x eat-compile-terminfo' when the Terminfo databases aren't
+ working properly.
+
+2023-03-31 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix directory tracking in Zsh
+
+ * integration/zsh (__eat_precmd): Use '$HOST' instead of
+ '$HOSTNAME'.
+
+2023-03-31 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Implement Zsh integration
+
+ * integration/zsh: New file.
+ * eat.texi (Shell Integration): Add instructions for Zsh.
+ * integration/bash: Always return zero on succuss.
+
+2023-03-30 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add new command 'eat-compile-terminfo'
+
+ * eat.el (eat-compile-terminfo): New command.
+ * eat.texi (Hello Terminal): Refer to 'Common Problems'.
+ * eat.texi (Common Problems): Add instructions to compile
+ Terminfo databases with 'eat-compile-terminfo'.
+
+2023-03-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Update manual to correctly describe command 'eat'
+
+ * eat.texi (Hello Terminal): Update to match with the current
+ behavior of command 'eat'.
+
+2023-03-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't prompt for program in M-x eat by default
+
+ * eat.el (eat): Prompt for program to run only if double prefix
+ argument is given, otherwise use the default one.
+
+2023-03-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix bugs in selection data manipulation code
+
+ * eat.el (eat--t-term): Put a vector of length 8 (instead of
+ 10) in 'cut-buffers' slot.
+ * eat.el (eat--t-manipulate-selection): Don't process the
+ targets '8' and '9', since they are not in the protocol.
+ Return correct list of queried targets to the client. Make
+ sure base64 encoded data doesn't contain line breaks.
+ * eat.el (eat--t-handle-output): Tolerate invalid targets in
+ OSC 52 (manipulate selection data).
+ * eat.el (eat--manipulate-kill-ring): Handle 'nil' correctly.
+
+2023-03-21 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix incompatiblity with Eshell on Emacs 28
+
+ * eat.el (eat--eshell-setup-proc-and-term): Set
+ 'eat--input-process' terminal parameter on Emacs 28.
+ * eat.el (eat-eshell-mode): Don't add advice
+ 'eat--eshell-set-input-process' on Emacs 28.
+
+2023-03-20 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Send input to correct process in Eshell pipeline
+
+ * eat.el (eat--process): Remove.
+ * eat.el (eat-mode): Don't make 'eat--process' buffer-local.
+ Use 'eat--terminal' to determine whether terminal is live.
+ * eat.el (eat--eshell-set-input-process): New function.
+ * eat.el (eat--eshell-local-mode): Don't make 'eat--process'
+ buffer-local. Add 'eat--eshell-set-input-process' as a advice
+ after 'eshell-resume-eval'.
+ * eat.el (eat-exec): Use the terminal parameters
+ 'eat--process', 'eat--input-process' and 'eat--output-process'
+ instead of the buffer-local variable 'eat--process' store the
+ process object.
+ * eat.el (eat--sentinel): Don't set 'eat--process' to nil.
+ * eat.el (eat--eshell-setup-proc-and-term): Set the terminal
+ parameters instead of buffer-local 'eat--process'.
+ * eat.el (eat--pre-prompt, eat--pre-cmd, eat-kill-process, eat)
+ (eat--send-input, eat--trace-eshell-adjust-make-process-args)
+ (eat--eshell-cleanup, eat--eshell-output-filter): Get the
+ process from terminal parameter.
+
+2023-02-08 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.texi (Querying Before Kill): New chapter
+
+2023-02-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Query when killing buffer when command is running
+
+ * eat.el (eat-query-before-killing-running-terminal): New user
+ option.
+ * eat.el (eat--pre-prompt): Unset process query on exit flag if
+ eat-query-before-killing-running-terminal is 'auto'.
+ * eat.el (eat--pre-cmd): Set process query on exit flag if
+ eat-query-before-killing-running-terminal is 'auto'.
+
+2023-01-22 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add many more semi-char mode exceptions
+
+ * eat.el (eat-semi-char-non-bound-keys)
+ (eat-eshell-semi-char-non-bound-keys): Add 81 more keys.
+
+2023-01-19 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Auto reload Eat when "semi-char" map is customized
+
+ * eat.el (eat--load-file-path, eat--being-loaded): New
+ variable.
+ * eat.el (eat-semi-char-non-bound-keys)
+ (eat-eshell-semi-char-non-bound-keys): Reload Eat when
+ customized. Document what to do if changed from Lisp.
+ * eat.el (eat-update-semi-char-mode-map)
+ (eat-eshell-update-semi-char-mode-map): New function.
+ * eat.el (eat-reload): New command.
+ * eat.texi (Semi-char Mode): Document what to do if the lists
+ of not bound keys are changed from Lisp.
+
+2023-01-18 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Document some new user options
+
+ * eat.texi (Semi-char Mode): Document
+ 'eat-semi-char-non-bound-keys' and
+ 'eat-eshell-semi-char-non-bound-keys'.
+ * eat.texi (Input Invisible): New section.
+
+2023-01-16 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Allow modifying semi-char key exceptions
+
+ * eat.el (eat-semi-char-non-bound-keys)
+ (eat-eshell-semi-char-non-bound-keys): New user option.
+ * eat.el (eat--prepare-semi-char-mode-map)
+ (eat--eshell-prepare-semi-char-mode-map): New function.
+ * eat.el (eat-semi-char-mode-map): Use
+ 'eat--prepare-semi-char-mode-map' to make the keymap.
+ * eat.el (eat-eshell-semi-char-mode-map): Use
+ 'eat--eshell-prepare-semi-char-mode-map' to make the keymap.
+
+2023-01-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Allow pasting from parent XTerm to Eat terminal
+
+ * eat.el (eat-xterm-paste): New command.
+ * eat.el (eat-mode-map, eat-eshell-emacs-mode-map): Bind
+ <xterm-paste> to 'ignore'.
+ * eat.el (eat-semi-char-mode-map, eat-char-mode-map)
+ (eat-eshell-semi-char-mode-map, eat-eshell-char-mode-map): Bind
+ <xterm-paste> to 'eat-xterm-paste'.
+
+2022-12-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't error while handling the sequence '\e[>c'
+
+ * eat.el (eat--t-send-device-attrs): Accept '((nil))' as the
+ value of the parameter PARAMS, but don't accept 'nil'.
+
+2022-12-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat): Use buffer name for process name
+
+ * eat.el (eat-eshell-exec-hook): Make customizable
+
+ * eat.el (eat-exec-hook): Make customizable
+
+2022-12-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Run eat-eshell-exec-hook as Eshell process is run
+
+ * eat.el (eat--eshell-setup-proc-and-term): Run
+ 'eat-eshell-exec-hook' at the very end.
+
+2022-12-22 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * README.org (Straight.el): New section
+
+2022-12-22 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't let font-lock to mess up text face
+
+ * eat.el (eat--t-repeated-insert, eat--t-write)
+ (eat--t-fix-partial-multi-col-char): Add 'font-lock-face' text
+ property along with 'face' to stop font-lock from removing the
+ face.
+
+2022-12-21 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix terminfo path on case-insensitive filesystems
+
+ * eat.el (eat--terminfo-path): New variable.
+ * eat.el (eat-term-terminfo-directory): Change default value to
+ 'PACKAGE-ROOT/terminfo/'.
+ * Makefile (terminfo): Don't depend on other targets. Make
+ directory 'terminfo'. Write terminfo to both 'e' and
+ '65' (hexadecimal number of ASCII 'e') directories.
+ * Makefile (e/eat-mono e/eat-color eat-256color e/eat-truecolor):
+ Remove target.
+ * README.org (Quelpa): Update recipe.
+
+2022-12-20 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat--t-handle-output): Fix NULL handling
+
+2022-12-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix typo in 'eat--t-scroll-up'
+
+ * eat.el (eat--t-scroll-up): Replace 'scroll-begin' with
+ 'scroll-end' in '(< scroll-end (eat--t-disp-width disp))',
+ since this will always evaluate to t, and thus it was most
+ probably a typo.
+
+2022-12-17 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Make sure symbol is used as face parameter value
+
+ * eat.el (eat-term-set-parameter): Make sure face parameter
+ values are symbols.
+
+2022-12-16 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Allow changing terminal faces terminal-locally
+
+ * eat.el (eat--t-term): New slots: bold-face, faint-face,
+ italic-face, slow-blink-face, fast-blink-face, color-0-face,
+ color-faces, font-faces. Use hash table for 'params' slot.
+ * eat.el (eat--t-set-sgr-params): Use new slot instead using
+ the faces directly.
+ * eat.el (eat-term-parameter): Update to work with 'params'
+ hash table.
+ * eat.el (eat-term-set-parameter): Update to work with 'params'
+ hash table. Handle the following parameters specially:
+ bold-face, faint-face, italic-face, slow-blink-face,
+ fast-blink-face, color-0-face, color-1-face, ...,
+ color-255-face, font-0-face, font-1-face, ..., font-9-face.
+
+2022-12-16 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Decoding UTF-8 encoded strings encoded as base64
+
+ * eat.el (eat--t-set-cwd): Decoding UTF-8 encoded strings encoded as
+ base64.
+ * eat.el (eat--t-manipulate-selection): Use 'ignore-errors'
+ instead of '(ignore-error ...)', since both macro expand to the
+ same code.
+ * eat.el (eat--t-set-cmd): Decoding UTF-8 encoded strings encoded as
+ base64. Use 'when-let*' instead of 'when' nested in 'let'.
+
+2022-12-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Decrease regexp usage while parsing output
+
+ * eat.el (eat--t-handle-output): Don't use regular expressions
+ while parsing plain text and CSI sequences. Remove useless
+ code from VT300-specific charset set sequence parser.
+
+2022-12-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix handling non-interactive processes in Eshell
+
+ * eat.el (eat--eshell-adjust-make-process-args): Check whether
+ the process going to be run will be interactive process.
+ * eat.el: Declare function 'eshell-interactive-output-p'.a
+
+2022-12-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't use '.*-char-property-.*' functions
+
+ * eat.el (eat--t-move-before-to-safe): Use
+ 'previous-single-property-change' instead of
+ '(previous-single-char-property-change'.
+ * eat.el (eat--t-join-long-line): Use 'get-text-property'
+ instead of 'get-char-property'. Handle properly the case where
+ 'next-single-property-change' returns nil.
+ * eat.el (eat--t-fix-partial-multi-col-char): Handle properly
+ the case where 'next-single-property-change' returns nil.
+
+2022-12-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Refactor 'eat--eshell-adjust-make-process-args'
+
+ * eat.el (eat--eshell-adjust-make-process-args): Move the
+ 'add-hook' out of 'unwind-protect'.
+
+2022-12-15 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Remove invisible spaces when killing text
+
+ * eat.el (eat-term-filter-string): Remove invisible spaces
+ preceding multi-column width characters.
+ * eat.el (eat--t-join-long-line)
+ (eat--t-fix-partial-multi-col-char): Use
+ 'next-single-property-change' instead of
+ 'next-single-char-property-change'.
+
+2022-12-14 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Refactor 'eat--eshell-adjust-make-process-args'
+
+ * eat.el (eat--eshell-adjust-make-process-args): Avoid
+ unnecessary function overrides. Overriding functions with
+ 'cl-letf*' is not well documented, and self-overriding a
+ function (override a function with its own definition) may not
+ a nop.
+
+2022-12-14 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Ask if 'stty' is unavailable in Eshell
+
+ * eat.el (eat-eshell-fallback-if-stty-not-available): New user
+ option.
+ * eat.el (eat--eshell-adjust-make-process-args): If 'stty' is
+ not available, use 'eat-eshell-fallback-if-stty-not-available'
+ to determine whether to continue terminal emulation or not.
+
+2022-12-12 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix shell prompt navigation
+
+ * eat.el (eat--post-prompt): Set 'eat--shell-prompt-begin' to
+ nil at the very end to ensure prompt end text properties are
+ put.
+
+2022-12-12 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Synchronize scroll on all windows showing terminal
+
+ * eat.el (eat--synchronize-scroll-windows): New function.
+ * eat.el (eat--synchronize-scroll)
+ (eat--eshell-synchronize-scroll): Take a single argument,
+ WINDOWS, list of windows to synchronize. The special value
+ 'buffer' can also be included, to synchronize the point in
+ buffer.
+ * eat.el (eat-self-input, eat-yank, eat-yank-from-kill-ring):
+ Pass the return value of 'eat--synchronize-scroll-windows' to
+ the function in 'eat--synchronize-scroll-function'.
+ * eat.el (eat--process-output-queue)
+ (eat--adjust-process-window-size, eat--eshell-output-filter)
+ Call 'eat--synchronize-scroll-windows' before doing anything,
+ save the result, and pass it as the first argument to the
+ function in 'eat--synchronize-scroll-function'.
+ * eat.el (eat--trace-replay-eval): Pass the return value of
+ 'get-buffer-window-list' to 'eat--synchronize-scroll'.
+
+2022-12-12 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't intercept background processes in Eshell
+
+ * eat.el (eat--eshell-adjust-make-process-args): Don't do any
+ change to the environment if 'eshell-current-subjob-p' is
+ non-nil.
+
+2022-12-11 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Check whether 'yank-transform-functions' is bound
+
+ * eat.el (eat-yank, eat-yank-from-kill-ring): Check whether
+ 'yank-transform-functions' is bound before using it's value.
+ The variable is not available in Emacs 28.
+
+2022-12-11 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * integration/bash: Check TERM before enabling
+
+ * eat.el (eat-eshell-emacs-mode-map): Disable undo
+
+2022-12-11 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use Eshell "emacs" mode map when process is live
+
+ * eat.el (eat-eshell-emacs-mode-map): Update docstring.
+ * eat.el (eat--eshell-process-running-mode): New
+ non-interactive minor mode.
+ * eat.el (eat--eshell-setup-proc-and-term): Enable
+ 'eat--eshell-process-running-mode'.
+ * eat.el (eat--eshell-cleanup): Disable
+ 'eat--eshell-process-running-mode'.
+ * eat.le (eat--eshell-local-mode): Don't use
+ 'eat-eshell-emacs-mode-map' as the mode keymap.
+
+2022-12-11 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Synchronize scrolling and point properly
+
+ * eat.el (eat--synchronize-scroll)
+ (eat--eshell-synchronize-scroll): Call 'set-window-point' in
+ addition to 'goto-char'.
+
+2022-12-11 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix invoking commands with eshell/sudo from Tramp
+
+ * eat.el (eat--eshell-adjust-make-process-args): Override
+ 'start-file-process' on Emacs 28, used by Eshell on Emacs 28.
+ Don't override 'make-process' on Emacs 28, Eshell doesn't use
+ that on Emacs 28. Set process filter and sentinel in
+ 'eshell-exec-hook' instead of 'make-process' advice.
+
+2022-12-11 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix Eshell working directory tracking
+
+ * eat.el (eat--eshell-local-mode): Call
+ 'eat--eshell-update-cwd'.
+ * eat.el (eat-eshell-mode): Don't call
+ 'eat--eshell-update-cwd'.
+
+2022-12-10 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix yanking text into terminal
+
+ * eat.el (eat-yank): Use simpler, saner and better approach to get the
+ yanked string instead of the previous stupid, insane and buggy
+ approach.
+ * eat.el (eat-yank-pop): Remove, because it's not cancel the text
+ already sent to the terminal.
+ * eat.el (eat-yank-from-kill-ring): New function. Behaves essentially
+ the same the previous (not properly working) 'eat-yank-pop'.
+ * eat.el (eat-semi-char-mode-map, eat-eshell-semi-char-mode-map):
+ Replace 'eat-yank-pop' with 'eat-yank-from-kill-ring'.
+
+2022-12-10 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Implement terminal parameters
+
+ * eat.el (eat--t-term): New slot: 'params'.
+ * eat.el (eat-term-parameter): New function and generalized
+ variable.
+ * eat.el (eat-set-term-parameter): New function.
+
+2022-12-09 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix terminal color reporting in text terminals
+
+ * eat.el (eat--t-report-foreground-color): Fix foreground color
+ reporting in text terminals.
+ * eat.el (eat--t-report-background-color): Fix background color
+ reporting in text terminals.
+
+2022-12-08 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Break combined 'setq'/'setf'/'setq-local's
+
+ When giving more than two arguments to 'setq', it becomes hard
+ to figure out what is assigned to what. As the number of
+ argument increases, the readablity of code decreases. This is
+ also true for 'setq-local'. For 'setf', the problem is even
+ greater, unlike 'setq', all arguments to 'setf' look the same.
+
+ * eat.el (eat--t-reset, eat--t-write, eat--t-save-cur)
+ (eat--t-restore-cur, eat--t-enable-alt-disp)
+ (eat--t-disable-alt-disp, eat--t-change-scroll-region)
+ (eat--t-set-sgr-params, eat--t-manipulate-selection)
+ (eat--t-resize, eat--blink-start-timers, eat-blink-mode)
+ (eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
+ (eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
+ (eat--eshell-cleanup, eat--eshell-adjust-make-process-args)
+ (eat--eshell-local-mode, eat--eshell-exec-visual)
+ (eat--trace-exec, eat--trace-eshell-adjust-make-process-args)
+ (eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
+ Break combined 'setq'/'setf'/'setq-local's.
+
+2022-12-08 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't 'cd' as root when using 'sudo' from Tramp
+
+ * eat.el (eat--eshell-setup-proc-and-term): Don't set
+ 'eat--eshell-invocation-directory'.
+ * eat.el (eat--eshell-update-cwd): New function.
+ * eat.el (eat--eshell-local-mode): Call
+ 'eat--eshell-update-cwd' when enabling the mode and add it to
+ 'eshell-directory-change-hook' to keep track of Eshell's
+ working directory.
+
+2022-12-08 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix prompt annotation bug trigger when shell exits
+
+ * eat.el (eat--correct-shell-prompt-mark-overlays): Make sure
+ 'eat--terminal' is non-nil.
+ * eat.el (eat--sentinel): Cancel timers, correct shell prompt
+ annotations for the final time, reset shell prompt annotation
+ related local variables.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Synchronize scrolling only when point is on cursor
+
+ * eat.el (eat--adjust-process-window-size): Synchronize
+ scrolling only when point is on cursor.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Escape control characters in trace output
+
+ * eat.el (eat--trace-log): Escape control
+ characters (codepoints from 0 to 31) in trace output.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Auto update 'eat-term-shell-integration-directory'
+
+ * eat.el: Auto update 'eat-term-shell-integration-directory' if
+ not modified.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Move Bash global variables to function
+
+ * integration/bash (__eat_current_command, __eat_exit_status)
+ (__eat_inhibit_preexec): Move to '__eat_enable_integration'.
+ * integration/bash (__eat_prompt_start, __eat_prompt_end)
+ (__eat_continuation_start, __eat_continuation_end): Move to
+ '__eat_enable_integration' and make local there.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Document annotation correction delay user option
+
+ * eat.texi (Performance Tuning): Document the purpose and the
+ use of 'eat-shell-prompt-annotation-correction-delay' user
+ option.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't accept 'nil' as annotation correction delay
+
+ * eat.el (eat-shell-prompt-annotation-correction-delay): Don't
+ accept 'nil'.
+ * eat.el (eat--process-output-queue): Don't accept value 'nil'
+ for 'eat-shell-prompt-annotation-correction-delay'.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Rename some symbols to reflect their purposes
+
+ * eat.el (eat-shell-prompt-annotation-delay): Rename to
+ 'eat-shell-prompt-annotation-correction-delay'.
+ * eat.el (eat--update-shell-prompt-mark-overlays): Rename to
+ 'eat--correct-shell-prompt-mark-overlays'.
+ * eat.el (eat--shell-prompt-annotation-update-timer): Rename to
+ 'eat--shell-prompt-annotation-correction-timer'.
+ * eat.el (eat-mode, eat--process-output-queue, eat--filter):
+ Update references to renamed symbols.
+
+2022-12-07 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * README.org: Add shell integration instructions
+
+ * eat-tests.el (eat-test-set-cwd): Update test
+
+ * eat.el (eat--t-term): Fix initial value of 'cwd'
+
+2022-12-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Document everything about shell integration
+
+ * eat.texi (Shell Integration): Move to be the first chapter of
+ Part III. Document everything about shell integration.
+ * eat.texi (Directory Tracking): Merge with the node 'Shell
+ Integration'.
+
+2022-12-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix prompt navigation when annotation is disabled
+
+ * eat.el (eat--pre-prompt): Always set
+ 'eat--shell-prompt-begin'.
+ * eat.el (eat--post-prompt): Always put special prompt end
+ marking text property.
+
+2022-12-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add shell prompt navigation commands
+
+ * eat.el (eat--post-prompt): Add special text property on the
+ last character of shell prompt.
+ * eat.el (eat-previous-shell-prompt, eat-next-shell-prompt):
+ New command.
+ * eat.el (eat-mode-map): Bind 'eat-previous-shell-prompt' and
+ 'eat-next-shell-prompt' to 'C-c C-p' and 'C-c C-n'
+ respectively.
+
+2022-12-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Annotate shell prompts
+
+ * eat.el (eat-enable-shell-prompt-annotation)
+ (eat-shell-prompt-annotation-position)
+ (eat-shell-prompt-annotation-running-margin-indicator)
+ (eat-shell-prompt-annotation-success-margin-indicator)
+ (eat-shell-prompt-annotation-failure-margin-indicator)
+ (eat-shell-prompt-annotation-delay): New user option.
+ * eat.el (eat-shell-prompt-annotation-running)
+ (eat-shell-prompt-annotation-success)
+ (eat-shell-prompt-annotation-failure): New face.
+ * eat.el (eat--shell-command-status, eat--shell-prompt-begin)
+ (eat--shell-prompt-mark, eat--shell-prompt-mark-overlays): New
+ variable.
+ * eat.el (eat--pre-prompt, eat--post-prompt)
+ (eat--update-shell-prompt-mark-overlays, eat--pre-cmd)
+ (eat--set-cmd-status): New function.
+ * eat.el (eat-mode): Make 'eat--shell-command-status',
+ 'eat--shell-prompt-begin', 'eat--shell-prompt-mark',
+ 'eat--shell-prompt-mark-overlays' and
+ 'eat--shell-prompt-annotation-update-timer' local. Set margin
+ width if shell prompt annotation is enabled.
+ * eat.el (eat--shell-prompt-annotation-update-timer): New
+ variable.
+ * eat.el (eat--process-output-queue): Call or schedule
+ 'eat--update-shell-prompt-mark-overlays' call.
+ * eat.el (eat--filter): Cancel timer
+ 'eat--shell-prompt-annotation-update-timer'.
+ * eat.el (eat-exec): Set prompt start & end and command start &
+ end functions.
+
+2022-12-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add shell commands run in Eat to Emacs history
+
+ * eat.el (eat-enable-shell-command-history): New user option.
+ * eat.el (eat--set-cmd): New function.
+ * eat.el (eat-exec, eat--eshell-setup-proc-and-term): Call
+ 'eat--set-cmd' when the shell reports the command being run.
+
+2022-12-06 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Tighter shell integration
+
+ * eat.el (eat--t-term): New slots: 'prompt-start-fn',
+ 'prompt-end-fn', 'cont-prompt-start-fn', 'cont-prompt-end-fn',
+ 'set-cmd-fn', 'cmd-start-fn', 'cmd-finish-fn'
+ * eat.el (eat--t-set-cwd): Accept three arguments in two
+ different formats.
+ * eat.el (eat--t-prompt-start, eat--t-prompt-end)
+ (eat--t-cont-prompt-start, eat--t-cont-prompt-end)
+ (eat--t-set-cmd, eat--t-cmd-start, eat--t-cmd-finish): New
+ function.
+ * eat.el (eat--t-handle-output): Accept Eat's own
+ OSC 51 ; e ; ... ST sequences.
+ * eat.el (eat-term-prompt-start-function)
+ (eat-term-prompt-end-function)
+ (eat-term-continuation-prompt-start-function)
+ (eat-term-continuation-prompt-end-function)
+ (eat-term-set-cmd-function, eat-term-cmd-start-function)
+ (eat-term-cmd-finish-function): New generalized variable.
+ * integration/bash (__eat_current_command, __eat_exit_status):
+ New variable.
+ * integration/bash (__eat_prompt_command): Send exit status of
+ last command, if applicable. Use Eat specific sequence to
+ report working directory. Set title.
+ * integration/bash (__eat_preexec): Report current command and
+ execution start.
+ * integration/bash (__eat_before_prompt_command): Set
+ '__eat_exit_status' to the exit status of the last command.
+ * integration/bash (__eat_prompt_start, __eat_prompt_end)
+ (__eat_continuation_start, __eat_continuation_end): New
+ variable, used as constant only to make the code more readable.
+ * integration/bash (__eat_enable_integration): Wrap 'PS1' and
+ 'PS2'. Don't set title from 'PS1'.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Calculate the number of lines on window properly
+
+ * eat.el (eat-exec, eat--eshell-setup-proc-and-term)
+ (eat--eshell-adjust-make-process-args)
+ (eat--eshell-synchronize-scroll): Calculate the number of
+ available lines on window properly.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Remap 'insert-char' to read and input a character
+
+ * eat.el (eat-input-char): New function.
+ * eat.el (eat-semi-char-mode-map)
+ (eat-eshell-semi-char-mode-map): Remap 'insert-char' to
+ 'eat-input-char'.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use full command as title in shell integration
+
+ * integration/bash (__eat_in_prompt_command): Rename to
+ '__eat_inhibit_preexec'.
+ * integration/bash (__eat_before_exec): Inhibit further
+ '__eat_preexec' calls until next prompt.
+ * integration/bash (__eat_preexec): Use 'history' to get the
+ real command typed by the user.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix Bash integration
+
+ * integration/bash (__eat_enable_integration): Fix moving
+ 'PROMPT_COMMAND' array elements.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el: Fix bright faces face definitions
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Refactor shell integration enabling code
+
+ * integration/bash (__eat_enable_integration): New function.
+ * integration/bash: Move enabling code to dedicated function.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Update title automatically in shell integration
+
+ * integration/bash (__eat_prompt_command): Remove extra '\'s.
+ * integration/bash (__eat_in_prompt_command): New variable.
+ * integration/bash (__eat_preexec, __eat_before_prompt_command)
+ (__eat_after_prompt_command, __eat_before_exec): New function.
+ * integration/bash: Modify PS1 to update terminal title when
+ displaying prompt. Add '__eat_before_exec' as 'DEBUG' trap
+ handler to update terminal title just before executing a
+ command. Prepend and append '__eat_before_prompt_command' and
+ '__eat_after_prompt_command' to 'PROMPT_COMMAND' to avoid
+ getting trapped in 'DEBUG' trap.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * README.org (Quelpa): Update recipe.
+
+ * term/eat.el: New file.
+
+2022-12-04 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Refer to NonGNU ELPA in README
+
+ * README.org (NonGNU ELPA Devel): Rename to NonGNU ELPA.
+ Change the code-snippet to use NonGNU ELPA (stable).
+
+2022-12-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * integration/bash: Add copyright notice.
+
+ * integration/bash: Use '__' prefix
+
+ * integration/bash: Append to array more cleanly
+
+ * integration/bash: Don't setup again on reload
+
+2022-12-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use more uniform names for tracer functions
+
+ * eat.el: Rename 'eat--eshell-trace-...' symbols to
+ 'eat--trace-eshell-...'.
+
+2022-12-03 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add shell integration script for GNU Bash
+
+ * integration/bash: New file.
+ * eat.el (eat-term-shell-integration-directory): New variable.
+ Contains path to the directory containing the scripts,
+ automatically updated when Eat is updated.
+ * eat.el (eat-exec, eat-eshell-mode): New enviroment variable
+ 'EAT_SHELL_INTEGRATION_DIR'.
+ * eat.texi (Shell Integration): New chapter.
+ * eat.texi (Directory Tracking): Refer to 'Shell Integration'.
+
+2022-12-01 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Check terminal contents while testing bell
+
+ * eat-tests.el (eat-test-character-sets): Check terminal
+ contents.
+
+2022-12-01 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Refer to Info manual to setup directory tracking
+
+ * eat.el (eat-enable-directory-tracking): Refer to Info manual.
+
+2022-12-01 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support directory tracking with OSC 7
+
+ * eat.el: Require 'url'.
+ * eat.el (eat-enable-directory-tracking): New user option.
+ * eat.el (eat--t-term): New slots: 'cwd' and 'set-cwd-fn'.
+ * eat.el (eat--t-set-cwd, eat-term-cwd): New function.
+ * eat.el (eat-term-set-cwd-function): New function and
+ generalized variable.
+ * eat.el (eat--t-handle-output): Handle OSC 7.
+ * eat.el (eat--set-cwd): New function.
+ * eat.el (eat-exec): Use 'eat--set-cwd' to change current
+ working directory.
+ * eat.el (eat--eshell-invocation-directory): New variable,
+ local in Eshell buffers when 'eat-eshell-mode' is enabled.
+ * eat.el (eat--eshell-setup-proc-and-term): Save the invocation
+ directory of process.
+ * eat.el (eat--eshell-cleanup): Revert working directory to
+ invocation directory.
+ * eat.el (eat--eshell-local-mode): When enabling, make
+ 'eat--eshell-invocation-directory' local variable and kill when
+ disabling.
+ * eat-tests.el (eat-test-set-cwd): New test.
+ * eat.texi (Directory Tracking): New chapter.
+
+2022-11-30 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix byte-compilation warnings on Emacs 28
+
+ * eat.el (eat-term-input-event): Fix byte-compilation warnings
+ on Emacs 28, caused by calling 'posn-col-row' with two
+ arguments on Emacs >= 29, which is not available on Emacs 28.
+
+2022-11-30 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el: Use loop to define color and font faces
+
+2022-11-30 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Document eat-eshell-visual-command-mode in manual
+
+ * eat.texi (Eshell Terminal): Document
+ 'eat-eshell-visual-command-mode' and suggest to set
+ 'eshell-visual-commands' to nil.
+
+2022-11-30 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Fix compatibility issues with Emacs 28
+
+ * eat.el: Require 'subr-x'.
+ * eat.el (eat-yank, eat-yank-pop): Pass three arguments to
+ 'mapconcat'.
+ * eat.el (eat--eshell-term-name): New function.
+ * eat.el (eat-eshell-mode): Use 'eat--eshell-term-name' instead
+ of using 'eat-term-name' directly.
+ * eat.el (eat-eshell-mode) [(< emacs-major-version 29)]: Use
+ 'eshell-last-async-proc' instead of 'eshell-last-async-procs'.
+ * eat.el (eat--eshell-adjust-make-process-args)
+ [(< emacs-major-version 29)]: Don't check and set ':filter' and
+ ':sentinel' of 'make-process' argument plist. Set process
+ filter and sentinel from 'eshell-exec-hook'.
+ * eat.el (eat--eshell-adjust-make-process-args): Call
+ 'eat--eshell-setup-proc-and-term' from 'eshell-exec-hook', not
+ just after 'make-process'.
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Don't put 'error' as the only then part of 'if'
+
+ * eat.el (eat-semi-char-mode, eat-char-mode): Don't put 'error'
+ as only then part of 'if'.
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use 'mapc' to make & kill multiple local variables
+
+ * eat.el (eat-blink-mode, eat--cursor-blink-mode, eat-mode)
+ (eat--eshell-local-mode, eat-trace-replay-mode): Use 'mapc' to
+ make & kill multiple local variables.
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Put declare-function and defvar outside functions
+
+ * eat.el (eat--flip-slow-blink-state)
+ (eat--flip-fast-blink-state, eat-blink-mode)
+ (eat--eshell-output-filter, eat--eshell-cleanup)
+ (eat--eshell-process-output-queue, eat--eshell-sentinel)
+ (eat-eshell-mode, eat--eshell-visual-sentinel)
+ (eat--eshell-exec-visual, eat-eshell-visual-command-mode)
+ (eat-project): Move 'declare-function's and 'defvar's outside.
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use 'vector' directly instead of backquote
+
+ * eat.el (eat-term-make-keymap): Use 'vector' directly instead
+ of backquote.
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat-term-make-keymap): Use 'cl-flet'
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use more readable '?\C-\s' instead of '?\C-\ '
+
+ * eat.el (eat-term-input-event, eat-term-make-keymap): Use more
+ readable '?\C-\s' instead of '?\C-\ '.
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat-mode): Fix char mode 'help-echo'
+
+ * eat.el (eat--bell): Use 'ding' instead of 'beep'
+
+ * eat.el (eat--trace-exec): Use "-*- mode: MD -*-"
+
+2022-11-29 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use 'setf' + 'plist-get' instead of 'plist-put'
+
+ * eat.el (eat--eshell-adjust-make-process-args): Use (setf (plist-get
+ ...) ...) instead of 'plist-put' without taking the result, which is
+ not guaranteed to always work.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Prefer 'and-let*' and 'when-let*' over 'when-let'
+
+ * eat.el (eat--t-set-sgr-params): Use 'and-let*' instead of 'when-let'
+ for side-effect free 'when-let'.
+ * eat.el (eat--flip-cursor-blink-state, eat--synchronize-scroll)
+ (eat-exec, eat--eshell-setup-proc-and-term)
+ (eat--eshell-synchronize-scroll, eat--eshell-visual-sentinel)
+ (eat--trace-replay-eval-next): Use 'when-let*' instead of 'when-let'
+ for 'when-let's with side-effect.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Prefer 'pcase-exhaustive' over 'pcase'
+
+ * eat.el (eat--t-erase-in-line, eat--t-erase-in-disp)
+ (eat--t-set-mouse-mode, eat--t-send-device-attrs)
+ (eat--t-handle-output, eat-term-input-event)
+ (eat--manipulate-kill-ring, eat--trace-replay-eval):
+ Prefer 'pcase-exhaustive' over 'pcase'.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * eat.el (eat--t-change-charset): Assert argument
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Combine multiple setq/setf/setq-local into one
+
+ * eat.el (eat--t-reset, eat--t-goto, eat--t-write)
+ (eat--t-save-cur, eat--t-enable-alt-disp)
+ (eat--t-change-scroll-region, eat--t-set-sgr-params)
+ (eat--t-manipulate-selection, eat--t-handle-output)
+ (eat--t-resize, eat--flip-slow-blink-state)
+ (eat--flip-fast-blink-state, eat-blink-mode)
+ (eat--cursor-blink-mode, eat--set-cursor, eat-self-input)
+ (eat-mode, eat-exec, eat--eshell-setup-proc-and-term)
+ (eat--eshell-cleanup, eat--eshell-local-mode)
+ (eat--eshell-exec-visual, eat--trace-exec)
+ (eat--eshell-trace-adjust-make-process-args)
+ (eat--trace-replay-eval, eat-trace-replay, eat-trace--cleanup):
+ Combine multiple setq/setf/setq-local into one wherever
+ possible.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Avoid copying STR to the extent possible
+
+ * eat.el (eat--t-write): Take two more optional arguments BEG
+ and END to avoid copying STR multiple times unneccessarily.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Support multi-column characters properly
+
+ * eat.el (eat--t-write): Use 'char-width' instead of the
+ unpredictable 'string-width' to support multi-column characters
+ properly.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use hash table to convert from charset
+
+ * eat.el (eat--t-dec-line-drawing-chars): New constant
+ containing the hash table.
+ * eat.el (eat--t-write): Use hash-table instead alist while
+ converting from DEC Line Drawing charset.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use as less let-bindings as possible
+
+ * eat.el (eat--t-goto-bol, eat--t-goto-eol)
+ (eat--t-repeated-insert, eat--t-cur-right, eat--t-cur-left)
+ (eat--t-cur-horizontal-abs, eat--t-beg-of-next-line)
+ (eat--t-beg-of-prev-line, eat--t-cur-down, eat--t-cur-up)
+ (eat--t-cur-vertical-abs, eat--t-scroll-up, eat--t-scroll-down)
+ (eat--t-write, eat--t-horizontal-tab)
+ (eat--t-horizontal-backtab, eat--t-reverse-index)
+ (eat--t-erase-in-line, eat--t-erase-in-disp)
+ (eat--t-insert-char, eat--t-delete-char, eat--t-erase-char)
+ (eat--t-insert-line, eat--t-delete-line)
+ (eat--t-repeat-last-char, eat--t-change-scroll-region)
+ (eat--t-send-device-attrs): Minimize let-binding count.
+ * eat.el (eat--t-break-long-line, eat--t-write)
+ (eat-trace-replay): Use replace 'propertize' call with already
+ propertized string.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Replace 'let*' with 'let' wherever possible
+
+ * eat.el (eat--t-eol, eat--t-reset, eat--t-erase-in-disp)
+ (eat--t-disable-alt-disp, eat--t-resize, eat-term-redisplay)
+ (eat-term-input-event, eat--adjust-process-window-size): Use
+ 'let' instead of 'let*' wherever possible.
+ * eat.el (eat--eshell-exec-visual): Use (VAR nil) form instead
+ of VAR form in 'let*' variable list.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * README.org (NonGNU ELPA Devel): New section
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Experimentally support for multi-column characters
+
+ * eat.el (eat--t-move-before-to-safe, eat--t-make-pos-safe)
+ (eat--t-fix-partial-multi-col-char): New function.
+ * eat.el (eat--t-write): Handle multi-column characters.
+ * eat.el (eat--t-insert-char, eat--t-delete-char)
+ (eat--t-erase-char): Handle multi-column characters on the
+ display while manipulating text.
+
+2022-11-28 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * .elpaignore: New file.
+
+2022-11-25 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Use third argument of posn-col-row on Emacs >= 29
+
+ * eat.el (eat-term-input-event): Use USE-WINDOW argument of
+ 'posn-col-row' to support text scaling properly, but only on
+ Emacs >= 29 since on Emacs 28 'posn-col-row' takes only one
+ argument.
+
+2022-11-24 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ * Makefile (all): Remove "check" and "changelog."
+
+2022-11-24 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add documentation file generation code to Makefile
+
+ * Makefile (info, dvi, html, pdf, eat.info, eat.dvi, eat.html)
+ (eat.pdf): New targets.
+ * Makefile (all): New dependency "info."
+ * Makefile (.PHONY): Add "info", "dvi", "html" and "pdf."
+
+2022-11-24 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Add proper dependencies to targets in Makefile
+
+ * Makefile (TIC): New variable.
+ * Makefile (eat.elc): Depend on eat.el.
+ * Makefile (e/eat-mono, e/eat-color, eat-256color)
+ (e/eat-truecolor): Depend on eat.ti.
+
+2022-11-24 Akib Azmain Turja <akibNOSPAMdisroot.org>
+
+ Implement the terminal
+
+ This includes everything written from 2022-08-15 up to now.
+ * .dir-locals.el:
+ * CONTRIBUTE:
+ * COPYING:
+ * Makefile:
+ * NEWS:
+ * README.org:
+ * eat-tests.el:
+ * eat.el:
+ * eat.texi:
+ * eat.ti:
+ * fdl.texi:
+ * gitlog-to-changelog:
+ * gpl.texi:
+ * make-changelog:
+ * texinfo.tex:
+ New file.
+
+;; Local Variables:
+;; coding: utf-8
+;; End:
+
+ Copyright (C) 2022-2023 Akib Azmain Turja.
+
+ This file is not part of GNU Emacs.
+
+ GNU Emacs 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.
+
+ GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
--- /dev/null
+Eat NEWS -- History of user-visible changes
+
+Copyright (C) 2022 Akib Azmain Turja.
+See the end of the file for license conditions.
+
+This file is about changes in Eat.
+
+Note:
++++ indicates that Eat manual have been updated.
+--- means no change in the manuals is needed.
+When you add a new item, use the appropriate mark if you are sure it
+applies, and please also update docstrings as needed.
+
+\f
+----------------------------------------------------------------------
+Adapted from etc/NEWS in Emacs source tree.
+
+This file is part of Eat and is not part of GNU Emacs.
+
+Eat 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.
+
+Eat 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
--- /dev/null
+ ━━━━━━━━━━━━━━━━━━━━━━━━━
+ EAT: EMULATE A TERMINAL
+ ━━━━━━━━━━━━━━━━━━━━━━━━━
+
+
+Eat's name self-explanatory, it stands for "Emulate A Terminal". Eat is
+a terminal emulator. It can run most (if not all) full-screen terminal
+programs, including Emacs.
+
+It is pretty fast, more than three times faster than Term, despite being
+implemented entirely in Emacs Lisp. So fast that you can comfortably
+run Emacs inside Eat, or even use your Emacs as a terminal multiplexer.
+
+It has many features that other Emacs terminal emulator still don't
+have, for example Sixel support, complete mouse support, shell
+integration, etc.
+
+It flickers less than other Emacs terminal emulator, so you get more
+performance and a smoother experience.
+
+To get the most out of Eat, you should also setup shell integration.
+
+
+1 Usage
+═══════
+
+ To start Eat, run `M-x eat'. Eat has four input modes:
+
+ • "semi-char" mode: This is the default input mode. Most keys are
+ bound to send the key to the terminal, except the following keys:
+ `C-\', `C-c', `C-x', `C-g', `C-h', `C-M-c', `C-u', `C-q', `M-x',
+ `M-:', `M-!', `M-&' and some other keys (see the user option
+ `eat-semi-char-non-bound-keys' for the complete list). The
+ following special keybinding are available:
+
+ • `C-q': Send next key to the terminal.
+ • `C-y': Like `yank', but send the text to the terminal.
+ • `M-y': Like `yank-pop', but send the text to the terminal.
+ • `C-c C-k': Kill process.
+ • `C-c C-e': Switch to "emacs" input mode.
+ • `C-c M-d': Switch to "char" input mode.
+ • `C-c C-l': Switch to "line" input mode.
+
+ • "emacs" mode: No special keybinding, except the following:
+
+ • `C-c C-j': Switch to "semi-char" input mode.
+ • `C-c M-d': Switch to "char" input mode.
+ • `C-c C-l': Switch to "line" input mode.
+ • `C-c C-k': Kill process.
+
+ • "char" mode: All supported keys are bound to send the key to the
+ terminal, except `C-M-m' or `M-RET', which is bound to switch to
+ "semi-char" input mode.
+
+ • "line" mode: Similar to Comint, Shell mode and Term line mode. In
+ this input mode, terminal input is sent one line at once, and you
+ can edit input line using the usual Emacs commands.
+
+ • `C-c C-e': Switch to "emacs" input mode
+ • `C-c C-j': Switch to "semi-char" input mode.
+ • `C-c M-d': Switch to "char" input mode.
+
+ If you like Eshell, then there is a good news for you. Eat integrates
+ with Eshell. Eat has two global minor modes for Eshell:
+
+ • `eat-eshell-visual-command-mode': Run visual commands with Eat
+ instead of Term.
+
+ • `eat-eshell-mode': Run Eat inside Eshell. After enabling this, you
+ can run full-screen terminal programs directly in Eshell. You have
+ the above input modes here too, except line mode and that `C-c C-k'
+ is not special (i.e. not bound by Eat) in "emacs" mode and "line"
+ mode.
+
+ You can add any of these to `eshell-load-hook' like the following:
+
+ ┌────
+ │ ;; For `eat-eshell-mode'.
+ │ (add-hook 'eshell-load-hook #'eat-eshell-mode)
+ │
+ │ ;; For `eat-eshell-visual-command-mode'.
+ │ (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode)
+ └────
+
+ To setup shell integration for GNU Bash, put the following at the end
+ of your `.bashrc':
+
+ #+begin_src sh [ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \ source
+ "$EAT_SHELL_INTEGRATION_DIR/bash" #+end_src sh
+
+ For Zsh, put the following in your `.zshrc':
+
+ #+begin_src sh [ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \ source
+ "$EAT_SHELL_INTEGRATION_DIR/zsh" #+end_src sh
+
+ There's a Info manual available with much more information, which can
+ be accessed with `C-h i m Eat', also available [here on the internet].
+
+
+[here on the internet]
+<https://elpa.nongnu.org/nongnu-devel/doc/eat.html>
+
+
+2 Installation
+══════════════
+
+ Eat requires at least Emacs 26.1 or above.
+
+
+2.1 NonGNU ELPA
+───────────────
+
+ Eat is available on NonGNU ELPA. So you can just do `M-x
+ package-install RET eat RET'.
+
+ If you're on Emacs 27 or earlier, you'll need to add NonGNU ELPA to
+ your `package-archives' by putting the following in your `init.el':
+
+ ┌────
+ │ (add-to-list 'package-archives
+ │ '("nongnu" . "https://elpa.nongnu.org/nongnu/"))
+ └────
+
+
+2.2 Quelpa
+──────────
+
+ ┌────
+ │ (quelpa '(eat :fetcher git
+ │ :url "https://codeberg.org/akib/emacs-eat"
+ │ :files ("*.el" ("term" "term/*.el") "*.texi"
+ │ "*.ti" ("terminfo/e" "terminfo/e/*")
+ │ ("terminfo/65" "terminfo/65/*")
+ │ ("integration" "integration/*")
+ │ (:exclude ".dir-locals.el" "*-tests.el"))))
+ └────
+
+
+2.3 Straight.el
+───────────────
+
+ ┌────
+ │ (straight-use-package
+ │ '(eat :type git
+ │ :host codeberg
+ │ :repo "akib/emacs-eat"
+ │ :files ("*.el" ("term" "term/*.el") "*.texi"
+ │ "*.ti" ("terminfo/e" "terminfo/e/*")
+ │ ("terminfo/65" "terminfo/65/*")
+ │ ("integration" "integration/*")
+ │ (:exclude ".dir-locals.el" "*-tests.el"))))
+ └────
+
+
+2.4 Manual
+──────────
+
+ Clone the repository and put it in your `load-path'.
+
+
+3 Comparison With Other Terminal Emulators
+══════════════════════════════════════════
+
+3.1 Term
+────────
+
+ Term is the Emacs built-in terminal emulator. Its terminal emulation
+ is pretty good too. But it's slow. It is so slow that Eat can beat
+ native-compiled Term even without byte-compilation, and when Eat is
+ byte-compiled, Eat is more than three times fast. Also, Term
+ flickers, just try to run `emacs -nw' in it. It doesn't support
+ remote connections, for example over Tramp. However, it's builtin
+ from the early days of Emacs, while Eat needs atleast Emacs 26.1.
+
+
+3.2 Vterm
+─────────
+
+ Vterm is powered by a C library, libvterm. For this reason, it can
+ process huge amount of text quickly. It is about 1.5 times faster
+ than Eat (byte-compiled or native-compiled) (and about 2.75 faster
+ then Eat without byte-compilation). But it doesn't have a char mode
+ (however you can make a char mode by putting some effort). And it too
+ flickers like Term, so despite being much faster that Eat, it seems to
+ be slow. If you need your terminal to handle huge bursts (megabytes)
+ of data, you should use Vterm.
+
+
+3.3 Coterm + Shell
+──────────────────
+
+ Coterm adds terminal emulation to Shell mode. Although the terminal
+ Coterm emulates is same as Term, it is much faster, about three times,
+ just a bit slow than Eat. However, it too flickers like other
+ terminals. Since it's an upgrade to Shell, you get all the features
+ of Shell like "line" mode, completion using your favorite completion
+ UI (Company, Corfu, etc), etc. Most of these features are available
+ in Eat, and also in Eat-Eshell-Mode as Eshell is similar to Shell,
+ however it's not Shell mode. Recommended if you like Shell.
+
+
+4 Acknowledgements
+══════════════════
+
+ This wouldn't have been possible if the following awesome softwares
+ didn't exist:
+
+ • [GNU Operating System]
+ • [St]
+ • [Kitty]
+ • [XTerm]
+ • [Linux-libre]
+ • [Term]
+ • [Coterm]
+ • [Shell]
+ • [Vterm]
+ • [Eshell]
+ • Numerous terminal programs
+ • And obviously, [GNU Emacs]
+
+
+[GNU Operating System] <https://gnu.org>
+
+[St] <https://st.suckless.org/>
+
+[Kitty] <https://sw.kovidgoyal.net/kitty/>
+
+[XTerm] <https://invisible-island.net/xterm/>
+
+[Linux-libre] <https://www.gnu.org/software/linux-libre/>
+
+[Term]
+<https://www.gnu.org/software/emacs/manual/html_node/emacs/Terminal-emulator.html>
+
+[Coterm] <https://repo.or.cz/emacs-coterm.git>
+
+[Shell]
+<https://www.gnu.org/software/emacs/manual/html_node/emacs/Interactive-Shell.html>
+
+[Vterm] <https://github.com/akermu/emacs-libvterm>
+
+[Eshell]
+<https://www.gnu.org/software/emacs/manual/html_node/eshell/index.html>
+
+[GNU Emacs] <https://www.gnu.org/software/emacs/>
--- /dev/null
+#+title: Eat: Emulate A Terminal
+
+Eat's name self-explanatory, it stands for "Emulate A Terminal". Eat
+is a terminal emulator. It can run most (if not all) full-screen
+terminal programs, including Emacs.
+
+It is pretty fast, more than three times faster than Term, despite
+being implemented entirely in Emacs Lisp. So fast that you can
+comfortably run Emacs inside Eat, or even use your Emacs as a terminal
+multiplexer.
+
+It has many features that other Emacs terminal emulator still don't
+have, for example Sixel support, complete mouse support, shell
+integration, etc.
+
+It flickers less than other Emacs terminal emulator, so you get more
+performance and a smoother experience.
+
+To get the most out of Eat, you should also setup shell integration.
+
+* Usage
+
+To start Eat, run =M-x eat=. Eat has four input modes:
+
+- "semi-char" mode: This is the default input mode. Most keys are
+ bound to send the key to the terminal, except the following keys:
+ =C-\=, =C-c=, =C-x=, =C-g=, =C-h=, =C-M-c=, =C-u=, =C-q=, =M-x=,
+ =M-:=, =M-!=, =M-&= and some other keys (see the user option
+ ~eat-semi-char-non-bound-keys~ for the complete list). The
+ following special keybinding are available:
+
+ - =C-q=: Send next key to the terminal.
+ - =C-y=: Like `yank', but send the text to the terminal.
+ - =M-y=: Like `yank-pop', but send the text to the terminal.
+ - =C-c C-k=: Kill process.
+ - =C-c C-e=: Switch to "emacs" input mode.
+ - =C-c M-d=: Switch to "char" input mode.
+ - =C-c C-l=: Switch to "line" input mode.
+
+- "emacs" mode: No special keybinding, except the following:
+
+ - =C-c C-j=: Switch to "semi-char" input mode.
+ - =C-c M-d=: Switch to "char" input mode.
+ - =C-c C-l=: Switch to "line" input mode.
+ - =C-c C-k=: Kill process.
+
+- "char" mode: All supported keys are bound to send the key to the
+ terminal, except =C-M-m= or =M-RET=, which is bound to switch to
+ "semi-char" input mode.
+
+- "line" mode: Similar to Comint, Shell mode and Term line mode. In
+ this input mode, terminal input is sent one line at once, and you
+ can edit input line using the usual Emacs commands.
+
+ - =C-c C-e=: Switch to "emacs" input mode
+ - =C-c C-j=: Switch to "semi-char" input mode.
+ - =C-c M-d=: Switch to "char" input mode.
+
+If you like Eshell, then there is a good news for you. Eat integrates
+with Eshell. Eat has two global minor modes for Eshell:
+
+- ~eat-eshell-visual-command-mode~: Run visual commands with Eat
+ instead of Term.
+
+- ~eat-eshell-mode~: Run Eat inside Eshell. After enabling this, you
+ can run full-screen terminal programs directly in Eshell. You have
+ the above input modes here too, except line mode and that =C-c C-k=
+ is not special (i.e. not bound by Eat) in "emacs" mode and "line"
+ mode.
+
+You can add any of these to ~eshell-load-hook~ like the following:
+
+#+begin_src emacs-lisp
+;; For `eat-eshell-mode'.
+(add-hook 'eshell-load-hook #'eat-eshell-mode)
+
+;; For `eat-eshell-visual-command-mode'.
+(add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode)
+#+end_src
+
+To setup shell integration for GNU Bash, put the following at the end
+of your ~.bashrc~:
+
+#+begin_src sh
+[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
+ source "$EAT_SHELL_INTEGRATION_DIR/bash"
+#+end_src sh
+
+For Zsh, put the following in your ~.zshrc~:
+
+#+begin_src sh
+[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
+ source "$EAT_SHELL_INTEGRATION_DIR/zsh"
+#+end_src sh
+
+There's a Info manual available with much more information, which can
+be accessed with =C-h i m Eat=, also available [[https://elpa.nongnu.org/nongnu-devel/doc/eat.html][here on the internet]].
+
+* Installation
+
+Eat requires at least Emacs 26.1 or above.
+
+** NonGNU ELPA
+
+Eat is available on NonGNU ELPA. So you can just do
+=M-x package-install RET eat RET=.
+
+If you're on Emacs 27 or earlier, you'll need to add NonGNU ELPA to
+your ~package-archives~ by putting the following in your ~init.el~:
+
+#+begin_src emacs-lisp
+(add-to-list 'package-archives
+ '("nongnu" . "https://elpa.nongnu.org/nongnu/"))
+#+end_src
+
+** Quelpa
+
+#+begin_src emacs-lisp
+(quelpa '(eat :fetcher git
+ :url "https://codeberg.org/akib/emacs-eat"
+ :files ("*.el" ("term" "term/*.el") "*.texi"
+ "*.ti" ("terminfo/e" "terminfo/e/*")
+ ("terminfo/65" "terminfo/65/*")
+ ("integration" "integration/*")
+ (:exclude ".dir-locals.el" "*-tests.el"))))
+#+end_src
+
+** Straight.el
+
+#+begin_src emacs-lisp
+(straight-use-package
+ '(eat :type git
+ :host codeberg
+ :repo "akib/emacs-eat"
+ :files ("*.el" ("term" "term/*.el") "*.texi"
+ "*.ti" ("terminfo/e" "terminfo/e/*")
+ ("terminfo/65" "terminfo/65/*")
+ ("integration" "integration/*")
+ (:exclude ".dir-locals.el" "*-tests.el"))))
+#+end_src
+
+** Manual
+
+Clone the repository and put it in your ~load-path~.
+
+* Comparison With Other Terminal Emulators
+
+** Term
+
+Term is the Emacs built-in terminal emulator. Its terminal emulation
+is pretty good too. But it's slow. It is so slow that Eat can beat
+native-compiled Term even without byte-compilation, and when Eat is
+byte-compiled, Eat is more than three times fast. Also, Term
+flickers, just try to run =emacs -nw= in it. It doesn't support
+remote connections, for example over Tramp. However, it's builtin
+from the early days of Emacs, while Eat needs atleast Emacs 26.1.
+
+** Vterm
+
+Vterm is powered by a C library, libvterm. For this reason, it can
+process huge amount of text quickly. It is about 1.5 times faster
+than Eat (byte-compiled or native-compiled) (and about 2.75 faster
+then Eat without byte-compilation). But it doesn't have a char mode
+(however you can make a char mode by putting some effort). And it too
+flickers like Term, so despite being much faster that Eat, it seems to
+be slow. If you need your terminal to handle huge bursts (megabytes)
+of data, you should use Vterm.
+
+** Coterm + Shell
+
+Coterm adds terminal emulation to Shell mode. Although the terminal
+Coterm emulates is same as Term, it is much faster, about three times,
+just a bit slow than Eat. However, it too flickers like other
+terminals. Since it's an upgrade to Shell, you get all the features
+of Shell like "line" mode, completion using your favorite completion
+UI (Company, Corfu, etc), etc. Most of these features are available
+in Eat, and also in Eat-Eshell-Mode as Eshell is similar to Shell,
+however it's not Shell mode. Recommended if you like Shell.
+
+* Acknowledgements
+
+This wouldn't have been possible if the following awesome softwares
+didn't exist:
+
+- [[https://gnu.org][GNU Operating System]]
+- [[https://st.suckless.org/][St]]
+- [[https://sw.kovidgoyal.net/kitty/][Kitty]]
+- [[https://invisible-island.net/xterm/][XTerm]]
+- [[https://www.gnu.org/software/linux-libre/][Linux-libre]]
+- [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Terminal-emulator.html][Term]]
+- [[https://repo.or.cz/emacs-coterm.git][Coterm]]
+- [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Interactive-Shell.html][Shell]]
+- [[https://github.com/akermu/emacs-libvterm][Vterm]]
+- [[https://www.gnu.org/software/emacs/manual/html_node/eshell/index.html][Eshell]]
+- Numerous terminal programs
+- And obviously, [[https://www.gnu.org/software/emacs/][GNU Emacs]]
--- /dev/null
+This is the file .../info/dir, which contains the
+topmost node of the Info hierarchy, called (dir)Top.
+The first time you invoke Info you start off looking at this node.
+\1f
+File: dir, Node: Top This is the top of the INFO tree
+
+ This (the Directory node) gives a menu of major topics.
+ Typing "q" exits, "H" lists all Info commands, "d" returns here,
+ "h" gives a primer for first-timers,
+ "mEmacs<Return>" visits the Emacs manual, etc.
+
+ In Emacs, you can click mouse button 2 on a menu item or cross reference
+ to select it.
+
+* Menu:
+
+Emacs
+* Eat: (eat). Emulate A Terminal.
--- /dev/null
+;;; eat-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*-
+;; Generated by the `loaddefs-generate' function.
+
+;; This file is part of GNU Emacs.
+
+;;; Code:
+
+(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
+
+
+\f
+;;; Generated autoloads from eat.el
+
+(autoload 'eat-term-make "eat" "\
+Make a Eat terminal at POSITION in BUFFER.
+
+(fn BUFFER POSITION)")
+(autoload 'eat "eat" "\
+Start a new Eat terminal emulator in a buffer.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG (like \\[universal-argument] 42 \\[eat]),
+switch to the session with that number, or create it if it doesn't
+already exist.
+
+With double prefix argument ARG, ask for the program to run and run it
+in a newly created session.
+
+PROGRAM can be a shell command.
+
+(fn &optional PROGRAM ARG)" t)
+(autoload 'eat-other-window "eat" "\
+Start a new Eat terminal emulator in a buffer in another window.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG switch to the session with that number, or
+create it if it doesn't already exist.
+
+With double prefix argument ARG, ask for the program to run and run it
+in a newly created session.
+
+PROGRAM can be a shell command.
+
+(fn &optional PROGRAM ARG)" t)
+(defvar eat-eshell-mode nil "\
+Non-nil if Eat-Eshell mode is enabled.
+See the `eat-eshell-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `eat-eshell-mode'.")
+(custom-autoload 'eat-eshell-mode "eat" nil)
+(autoload 'eat-eshell-mode "eat" "\
+Toggle Eat terminal emulation in Eshell.
+
+This is a global minor mode. If called interactively, toggle the
+`Eat-Eshell mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='eat-eshell-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t)
+(defvar eat-eshell-visual-command-mode nil "\
+Non-nil if Eat-Eshell-Visual-Command mode is enabled.
+See the `eat-eshell-visual-command-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `eat-eshell-visual-command-mode'.")
+(custom-autoload 'eat-eshell-visual-command-mode "eat" nil)
+(autoload 'eat-eshell-visual-command-mode "eat" "\
+Toggle running Eshell visual commands with Eat.
+
+This is a global minor mode. If called interactively, toggle the
+`Eat-Eshell-Visual-Command mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='eat-eshell-visual-command-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t)
+(autoload 'eat-project "eat" "\
+Start Eat in the current project's root directory.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG (like
+\\[universal-argument] 42 \\[eat-project]), switch to the session with
+that number, or create it if it doesn't already exist.
+
+(fn &optional ARG)" t)
+(autoload 'eat-project-other-window "eat" "\
+Start Eat in the current project root directory in another window.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG (like
+\\[universal-argument] 42 \\[eat-project]), switch to the session with
+that number, or create it if it doesn't already exist.
+
+(fn &optional ARG)" t)
+(register-definition-prefixes "eat" '("eat-"))
+\f
+;;; End of scraped data
+
+(provide 'eat-autoloads)
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; no-native-compile: t
+;; coding: utf-8-emacs-unix
+;; End:
+
+;;; eat-autoloads.el ends here
--- /dev/null
+;; Generated package description from eat.el -*- no-byte-compile: t -*-
+(define-package "eat" "0.9.4" "Emulate A Terminal, in a region, in a buffer and in Eshell" '((emacs "26.1") (compat "29.1")) :commit "c91451f2d17453c19d3fa76faa4945cbe54e14ce" :authors '(("Akib Azmain Turja" . "akibNOSPAMdisroot.org")) :maintainer '("Akib Azmain Turja" . "akibNOSPAMdisroot.org") :keywords '("terminals" "processes") :url "https://codeberg.org/akib/emacs-eat")
--- /dev/null
+;;; eat.el --- Emulate A Terminal, in a region, in a buffer and in Eshell -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022, 2023 Akib Azmain Turja.
+
+;; Author: Akib Azmain Turja <akibNOSPAMdisroot.org>
+;; Created: 2022-08-15
+;; Version: 0.9.4
+;; Package-Requires: ((emacs "26.1") (compat "29.1"))
+;; Keywords: terminals processes
+;; Homepage: https://codeberg.org/akib/emacs-eat
+
+;; This file is not part of GNU Emacs.
+
+;; This file 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, 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.
+
+;; For a full copy of the GNU General Public License
+;; see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Eat's name self-explanatory, it stands for "Emulate A Terminal".
+;; Eat is a terminal emulator. It can run most (if not all)
+;; full-screen terminal programs, including Emacs.
+
+;; It is pretty fast, more than three times faster than Term, despite
+;; being implemented entirely in Emacs Lisp. So fast that you can
+;; comfortably run Emacs inside Eat, or even use your Emacs as a
+;; terminal multiplexer.
+
+;; It has many feature that other Emacs terminal emulator still don't
+;; have, for example complete mouse support.
+
+;; It flickers less than other Emacs terminal emulator, so you get
+;; more performance and a smooth experience.
+
+;; To start Eat, run M-x eat. Eat has three keybinding modes:
+
+;; * "semi-char" mode: This is the default keybinding mode. Most
+;; keys are bound to send the key to the terminal, except the
+;; following keys: `C-\', `C-c', `C-x', `C-g', `C-h', `C-M-c',
+;; `C-u', `M-x', `M-:', `M-!', `M-&' and some other keys (see the
+;; user option `eat-semi-char-non-bound-keys' for the complete
+;; list). The following special keybinding are available:
+
+;; * `C-q': Send next key to the terminal.
+;; * `C-y': Like `yank', but send the text to the terminal.
+;; * `M-y': Like `yank-pop', but send the text to the terminal.
+;; * `C-c' `C-k': Kill process.
+;; * `C-c' `C-e': Switch to "emacs" keybinding mode.
+;; * `C-c' `M-d': Switch to "char" keybinding mode.
+
+;; * "emacs" mode: No special keybinding, except the following:
+
+;; * `C-c' `C-j': Switch to "semi-char" keybinding mode.
+;; * `C-c' `M-d': Switch to "char" keybinding mode.
+;; * `C-c' `C-k': Kill process.
+
+;; * "char" mode: All supported keys are bound to send the key to
+;; the terminal, except `C-M-m' or `M-RET', which is bound to
+;; switch to "semi-char" keybinding mode.
+
+;; If you like Eshell, then there is a good news for you. Eat
+;; integrates with Eshell. Eat has two global minor modes for Eshell:
+
+;; * `eat-eshell-visual-command-mode': Run visual commands with Eat
+;; instead of Term.
+
+;; * `eat-eshell-mode': Run Eat inside Eshell. After enabling this,
+;; you can run full-screen terminal programs directly in Eshell.
+;; You have three keybinding modes here too, except that `C-c'
+;; `C-k' is not special (i.e. not bound by Eat) in "emacs" mode
+;; and "line" mode.
+
+;;; Code:
+
+(require 'compat)
+(require 'subr-x)
+(require 'cl-lib)
+(require 'ansi-color)
+(require 'color)
+(require 'shell)
+(require 'term)
+(require 'url)
+
+;; Needed by `eat-reload'.
+(defvar eat--being-loaded nil
+ "Non-nil means Eat is being loaded.")
+
+(setq eat--being-loaded t)
+
+\f
+;;;; User Options.
+
+(defgroup eat nil
+ "Emulate A Terminal."
+ :group 'processes
+ :group 'terminals
+ :link '(url-link "https://codeberg.org/akib/emacs-eat"))
+
+(defgroup eat-term nil
+ "Eat terminal emulator."
+ :group 'eat)
+
+(defgroup eat-ui nil
+ "Eat user interface."
+ :group 'eat)
+
+(defgroup eat-eshell nil
+ "Eat Eshell integration."
+ :group 'eat)
+
+(defcustom eat-buffer-name "*eat*"
+ "The basename used for Eat buffers.
+
+This is the default name used when running Eat."
+ :type 'string
+ :group 'eat-ui)
+
+(defcustom eat-kill-buffer-on-exit nil
+ "Non-nil means automatically kill Eat buffer when process exits."
+ :type 'boolean
+ :group 'eat-ui)
+
+(defcustom eat-term-scrollback-size 131072 ; 128 K
+ "Size of scrollback area in characters. nil means unlimited."
+ :type '(choice natnum (const nil))
+ :group 'eat-term
+ :group 'eat-ui)
+
+(defcustom eat-enable-kill-from-terminal t
+ "Non-nil means allow terminal program to add text to `kill-ring'.
+
+When non-nil, terminal program can send special escape sequence to add
+some text to `kill-ring'."
+ :type 'boolean
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-enable-yank-to-terminal nil
+ "Non-nil means allow terminal program to get text from `kill-ring'.
+
+When non-nil, terminal program can get killed text from `kill-ring'.
+This is left disabled for security reasons."
+ :type 'boolean
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-query-before-killing-running-terminal 'auto
+ "Whether to query before killing running terminal.
+
+If the value is t, always query. If the value is nil, never query.
+If the value is `auto', query if a shell command is running (shell
+integration needs to be enabled to use this properly)."
+ :type '(choice (const :tag "Yes" t)
+ (const :tag "No" nil)
+ (const :tag "If a shell command is running" auto))
+ :group 'eat-ui)
+
+(defcustom eat-eshell-fallback-if-stty-not-available 'ask
+ "What to do if `stty' is unavailable.
+
+`stty' is a dependency to setup terminal. If `stty' is unavailable,
+Eat won't be able to setup terminal, so any input won't be visible.
+
+The value should be any of the following:
+
+nil Do nothing.
+t Fallback to plain Eshell if `stty' is not available.
+`ask' Ask what to do.
+FUNCTION Call FUNCTION with the command and arguments (using
+ `apply') and fallback to plain Eshell if it returns
+ nil."
+ :type '(radio (const :tag "Do nothing" nil)
+ (const :tag "Fallback to plain Eshell" t)
+ (const :tag "Ask interactively" ask)
+ (function :tag "Function"))
+ :group 'eat-eshell)
+
+(defcustom eat-sixel-scale 1.0
+ "Scale Sixel images by this amount."
+ :type 'number
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-sixel-aspect-ratio 1.0
+ "Aspect ratio of Sixel images.
+
+The value is a positive number specifying the ratio of the width and
+height of a Sixel pixel. For example, the value of 1.5 means the
+aspect ratio of 3:2."
+ :type 'number
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-sixel-render-formats
+ '(xpm svg half-block background none)
+ "List of formats to render Sixel, in order of preference."
+ :type '(repeat (choice (const :tag "XPM Image" xpm)
+ (const :tag "SVG Image" svg)
+ (const :tag "UTF-8 half block" half-block)
+ (const :tag "Background color" background)
+ (const :tag "None" none)))
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-line-input-ring-size 1000
+ "Number of input history items to keep."
+ :type 'natnum
+ :group 'eat-ui)
+
+(defcustom eat-line-auto-move-to-input t
+ "Non-nil means move to input line when inserting characters."
+ :type 'boolean
+ :group 'eat-ui)
+
+(defcustom eat-line-move-point-for-matching-input 'after-input
+ "Controls where to place point after matching input.
+
+\\<eat-line-mode-map>This influences the commands \
+\\[eat-line-previous-matching-input-from-input] and \
+\\[eat-line-next-matching-input-from-input].
+If `after-input', point will be positioned after the input typed
+by the user, but before the rest of the history entry that has
+been inserted. If `end-of-line', point will be positioned at the
+end of the current logical (not visual) line after insertion."
+ :type '(radio (const :tag "Stay after input" after-input)
+ (const :tag "Move to end of line" end-of-line))
+ :group 'eat-ui)
+
+(defcustom eat-line-input-history-isearch nil
+ "Non-nil to Isearch in input history only, not in the terminal.
+
+If t, usual Isearch keys like \\[isearch-backward] and \
+\\[isearch-backward-regexp] in Eat buffer search in
+the input history. If `dwim', Isearch keys search in the input
+history only when initial point position is on input line. When
+starting Isearch from other parts of the Eat buffer, they search in
+the Eat buffer. If nil, Isearch operates on the whole Eat buffer."
+ :type '(choice (const :tag "Don't search in input history" nil)
+ (const :tag "When point is on input line initially, \
+search history"
+ dwim)
+ (const :tag "Always search in input history" t))
+ :group 'eat-ui)
+
+(defcustom eat-line-input-send-function #'eat-line-send-default
+ "Function to send the shell prompt input.
+
+The function is called without any argument. The buffer is narrowed
+to the input. The function may modify the input but mustn't modify
+the buffer restrictions. It should call
+`eat-line-send-default' to send the final output."
+ :type 'function
+ :group 'eat-ui)
+
+(defcustom eat-semi-char-non-bound-keys
+ '([?\C-x] [?\C-\\] [?\C-q] [?\C-g] [?\C-h] [?\e ?\C-c] [?\C-u]
+ [?\e ?x] [?\e ?:] [?\e ?!] [?\e ?&]
+ [C-insert] [M-insert] [S-insert] [C-M-insert]
+ [C-S-insert] [M-S-insert] [C-M-S-insert]
+ [C-delete] [M-delete] [S-delete] [C-M-delete]
+ [C-S-delete] [M-S-delete] [C-M-S-delete]
+ [C-deletechar] [M-deletechar]
+ [S-deletechar] [C-M-deletechar] [C-S-deletechar]
+ [M-S-deletechar] [C-M-S-deletechar]
+ [C-up] [C-down] [C-right] [C-left]
+ [M-up] [M-down] [M-right] [M-left]
+ [S-up] [S-down] [S-right] [S-left]
+ [C-M-up] [C-M-down] [C-M-right] [C-M-left]
+ [C-S-up] [C-S-down] [C-S-right] [C-S-left]
+ [M-S-up] [M-S-down] [M-S-right] [M-S-left]
+ [C-M-S-up] [C-M-S-down] [C-M-S-right] [C-M-S-left]
+ [C-home] [M-home] [S-home] [C-M-home] [C-S-home]
+ [M-S-home] [C-M-S-home]
+ [C-end] [M-end] [S-end] [C-M-end] [C-S-end]
+ [M-S-end] [C-M-S-end]
+ [C-prior] [M-prior] [S-prior] [C-M-prior]
+ [C-S-prior] [M-S-prior] [C-M-S-prior]
+ [C-next] [M-next] [S-next] [C-M-next] [C-S-next]
+ [M-S-next] [C-M-S-next])
+ "List of keys not bound in Eat \"semi-char\" mode.
+
+Keys appearing in this list are not bound to send the key to terminal.
+Eat might still bound them to do something else (for example, changing
+keybinding mode).
+
+Each element is a vector of form [KEY] or [?\\e KEY], meaning KEY or
+M-KEY shouldn't be bound. KEY shouldn't contain meta (Alt) modifier.
+
+When changing this from Lisp, make sure to call
+`eat-update-semi-char-mode-map' to update the keymap and reload Eat to
+make the changes effective."
+ :type '(repeat sexp)
+ :set (lambda (sym val)
+ (set-default-toplevel-value sym val)
+ (when (and (not eat--being-loaded)
+ (boundp 'eat-semi-char-mode-map))
+ (eat-update-semi-char-mode-map)
+ (let ((after-load-alist nil)
+ (after-load-functions nil))
+ (eat-reload))))
+ :group 'eat-ui)
+
+(defcustom eat-eshell-semi-char-non-bound-keys
+ '([?\C-\\] [?\C-x] [?\C-g] [?\C-h] [?\e ?\C-c] [?\C-u] [?\C-q]
+ [?\e ?x] [?\e ?:] [?\e ?!] [?\e ?&]
+ [C-insert] [M-insert] [S-insert] [C-M-insert]
+ [C-S-insert] [M-S-insert] [C-M-S-insert]
+ [C-delete] [M-delete] [S-delete] [C-M-delete]
+ [C-S-delete] [M-S-delete] [C-M-S-delete]
+ [C-deletechar] [M-deletechar]
+ [S-deletechar] [C-M-deletechar] [C-S-deletechar]
+ [M-S-deletechar] [C-M-S-deletechar]
+ [C-up] [C-down] [C-right] [C-left]
+ [M-up] [M-down] [M-right] [M-left]
+ [S-up] [S-down] [S-right] [S-left]
+ [C-M-up] [C-M-down] [C-M-right] [C-M-left]
+ [C-S-up] [C-S-down] [C-S-right] [C-S-left]
+ [M-S-up] [M-S-down] [M-S-right] [M-S-left]
+ [C-M-S-up] [C-M-S-down] [C-M-S-right] [C-M-S-left]
+ [C-home] [M-home] [S-home] [C-M-home] [C-S-home]
+ [M-S-home] [C-M-S-home]
+ [C-end] [M-end] [S-end] [C-M-end] [C-S-end]
+ [M-S-end] [C-M-S-end]
+ [C-prior] [M-prior] [S-prior] [C-M-prior]
+ [C-S-prior] [M-S-prior] [C-M-S-prior]
+ [C-next] [M-next] [S-next] [C-M-next] [C-S-next]
+ [M-S-next] [C-M-S-next])
+ "List of keys not bound in Eat-Eshell \"semi-char\" mode.
+
+Keys appearing in this list are not bound to send the key to terminal.
+Eat might still bound them to do something else (for example, changing
+keybinding mode).
+
+Each element is a vector of form [KEY] or [?\\e KEY], meaning KEY or
+M-KEY shouldn't be bound. KEY shouldn't contain meta (Alt) modifier.
+
+When changing this from Lisp, make sure to call
+`eat-eshell-update-semi-char-mode-map' to update the keymap and reload
+Eat to make the changes effective."
+ :type '(repeat sexp)
+ :set (lambda (sym val)
+ (set-default-toplevel-value sym val)
+ (when (and (not eat--being-loaded)
+ (boundp 'eat-eshell-semi-char-mode-map))
+ (eat-eshell-update-semi-char-mode-map)
+ (let ((after-load-alist nil)
+ (after-load-functions nil))
+ (eat-reload))))
+ :group 'eat-eshell)
+
+(defcustom eat-enable-directory-tracking t
+ "Non-nil means do directory tracking.
+
+When non-nil, Eat will track the working directory of program. You
+need to configure the program to send current working directory
+information. See Info node `(eat)Directory Tracking' for instructions
+to setup your shell."
+ :type 'boolean
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-enable-shell-command-history t
+ "Non-nil means add shell commands to Emacs history.
+
+When non-nil, any command you run in your shell will also appear in
+the history of commands like `eat', `shell-command' and
+`async-shell-command'."
+ :type 'boolean
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-message-handler-alist nil
+ "Alist of message handler name and its handler function.
+
+The keys are the names of message handlers, and the values are their
+respective handler functions.
+
+Shells can send Eat messages, as defined in this user option. If an
+appropiate message handler is defined, it's called with the other
+arguments, otherwise it's ignored."
+ :type '(alist :key-type string
+ :value-type function)
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-enable-auto-line-mode nil
+ "Non-nil means switch to line mode automatically on shell prompt."
+ :type 'boolean
+ :group 'eat-ui)
+
+(defcustom eat-enable-shell-prompt-annotation t
+ "Non-nil means annotate shell prompt with the status of command.
+
+When non-nil, display a mark in front of shell prompt describing the
+status of the command executed in that prompt."
+ :type 'boolean
+ :group 'eat-ui)
+
+(defcustom eat-shell-prompt-annotation-position 'left-margin
+ "The position where to display shell prompt annotation.
+
+The value can be one of the following:
+
+`left-margin' Use the left margin.
+`right-margin' Use the right margin."
+ :type '(choice (const :tag "Left margin" left-margin)
+ (const :tag "Right margin" right-margin))
+ :group 'eat-ui)
+
+(defcustom eat-shell-prompt-annotation-running-margin-indicator "-"
+ "String in margin annotation to indicate the command is running."
+ :type 'string
+ :group 'eat-ui)
+
+(defface eat-shell-prompt-annotation-running
+ '((t :inherit compilation-info))
+ "Face used in annotation to indicate the command is running."
+ :group 'eat-ui)
+
+(defcustom eat-shell-prompt-annotation-success-margin-indicator "0"
+ "String in margin annotation to indicate the command has succeeded."
+ :type 'string
+ :group 'eat-ui)
+
+(defface eat-shell-prompt-annotation-success
+ '((t :inherit success))
+ "Face used in annotation to indicate the command has succeeded."
+ :group 'eat-ui)
+
+(defcustom eat-shell-prompt-annotation-failure-margin-indicator "X"
+ "String in margin annotation to indicate the command has failed."
+ :type 'string
+ :group 'eat-ui)
+
+(defface eat-shell-prompt-annotation-failure
+ '((t :inherit error))
+ "Face used in annotation to indicate the command has failed."
+ :group 'eat-ui)
+
+(defcustom eat-shell-prompt-annotation-correction-delay 0.1
+ "Seconds to wait before correcting shell prompt annotations.
+
+Wait this many second after terminal update before correcting shell
+prompt annotation."
+ :type 'number
+ :group 'eat-ui)
+
+(defcustom eat-exec-hook nil
+ "Hook run after `eat' executes a commamnd.
+
+The hook is run with the process run in the terminal as the only
+argument."
+ :type 'hook
+ :group 'eat-ui)
+
+(defcustom eat-update-hook nil
+ "Hook run after the terminal in a Eat buffer is updated."
+ :type 'hook
+ :group 'eat-ui)
+
+(defcustom eat-exit-hook nil
+ "Hook run after the command executed by `eat' exits.
+
+The hook is run with the process that just exited as the only
+argument."
+ :type 'hook
+ :group 'eat-ui)
+
+(defcustom eat-eshell-exec-hook nil
+ "Hook run after a terminal is created in Eshell."
+ :type 'hook
+ :group 'eat-eshell)
+
+(defcustom eat-eshell-update-hook nil
+ "Hook run after the terminal in a Eshell buffer is updated."
+ :type 'hook
+ :group 'eat-eshell)
+
+(defcustom eat-eshell-exit-hook nil
+ "Hook run after the terminal in Eshell is deleted."
+ :type 'hook
+ :group 'eat-eshell)
+
+(defconst eat--cursor-type-value-type
+ (let ((cur-type
+ '(choice
+ (const :tag "Frame default" t)
+ (const :tag "Filled box" box)
+ (cons :tag "Box with specified size" (const box) integer)
+ (const :tag "Hollow cursor" hollow)
+ (const :tag "Vertical bar" bar)
+ (cons :tag "Vertical bar with specified height" (const bar)
+ integer)
+ (const :tag "Horizontal bar" hbar)
+ (cons :tag "Horizontal bar with specified width"
+ (const hbar) integer)
+ (const :tag "None " nil))))
+ `(list
+ ,cur-type
+ (choice
+ (const :tag "No blinking" nil)
+ (number :tag "Blinking frequency"))
+ ,cur-type))
+ "Custom type specification for Eat's cursor type variables.")
+
+(defcustom eat-invisible-cursor-type '(nil nil nil)
+ "Type of cursor to use as invisible cursor in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-default-cursor-type
+ `(,(default-value 'cursor-type) nil nil)
+ "Cursor to use in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-very-visible-cursor-type
+ `(,(default-value 'cursor-type) 2 hollow)
+ "Very visible cursor to use in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-vertical-bar-cursor-type '(bar nil nil)
+ "Vertical bar cursor to use in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-very-visible-vertical-bar-cursor-type '(bar 2 nil)
+ "Very visible vertical bar cursor to use in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-horizontal-bar-cursor-type '(hbar nil nil)
+ "Horizontal bar cursor to use in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-very-visible-horizontal-bar-cursor-type '(hbar 2 nil)
+ "Very visible horizontal bar cursor to use in Eat buffer.
+
+The value is a list of form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF).
+
+When the cursor is on, CURSOR-ON is used as `cursor-type', which see.
+BLINKING-FREQUENCY is the blinking frequency of cursor's blinking.
+When the cursor is off, CURSOR-OFF is used as `cursor-type'. This
+should be nil when cursor is not blinking."
+ :type eat--cursor-type-value-type
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-minimum-latency 0.008
+ "Minimum display latency in seconds.
+
+Lowering it too much may cause (or increase) flickering and decrease
+performance due to too many redisplays. Increasing it too much will
+cause the terminal to feel less responsive. Try to increase this
+value if the terminal flickers."
+ :type 'number
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-maximum-latency 0.033
+ "Minimum display latency in seconds.
+
+Increasing it too much may make the terminal feel less responsive in
+case of huge burst of output. Try to increase this value if the
+terminal flickers. Try to lower the value if the terminal feels less
+responsive."
+ :type 'number
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-term-name #'eat-term-get-suitable-term-name
+ "Value for the `TERM' environment variable.
+
+The value can also be a function. In that case, the function is
+called without any argument and the return value is used as the value.
+For example, this can set to `eat-term-get-suitable-term-name' to set
+the value according to the number of colors supported by the current
+display.
+
+This value is used by terminal programs to identify the terminal."
+ :type '(choice
+ (string :tag "Value")
+ (const :tag "Automatic" eat-term-get-suitable-term-name)
+ (function :tag "Function"))
+ :group 'eat-term)
+
+;; Upgrading Eat causes `eat-term-terminfo-directory' and
+;; `eat-term-shell-integration-directory' to be outdated, so update it
+;; if not modified by user (or something else).
+(defvar eat--load-file-path nil
+ "Path to currently loaded Eat.")
+
+(defvar eat--install-path nil
+ "Path to directory where Eat is installed.")
+
+(defvar eat--terminfo-path nil
+ "Path to directory where Terminfo databases are installed.")
+
+(defvar eat--shell-integration-path nil
+ "Path to directory where shell integration scripts are installed.")
+
+(setq eat--load-file-path (or load-file-name buffer-file-name))
+
+(setq eat--install-path
+ (copy-sequence (file-name-directory eat--load-file-path)))
+
+(defvar eat-term-terminfo-directory)
+(defvar eat-term-shell-integration-directory)
+(let ((old-terminfo-path eat--terminfo-path)
+ (old-shell-integration-path eat--shell-integration-path))
+ (setq eat--terminfo-path
+ (expand-file-name "terminfo" eat--install-path))
+ (setq eat--shell-integration-path
+ (expand-file-name "integration" eat--install-path))
+
+ (defcustom eat-term-terminfo-directory eat--terminfo-path
+ "Directory where required terminfo databases can be found.
+
+This value is used by terminal programs to find the terminfo databases
+that describe the capabilities of the terminal."
+ :type 'directory
+ :group 'eat-term)
+
+ (defcustom eat-term-shell-integration-directory
+ eat--shell-integration-path
+ "Directory where Eat shell integration scripts can be found.
+
+This value is exposed to terminal programs as
+`EAT_SHELL_INTEGRATION_DIR' environment variable."
+ :type 'directory
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+ (when (eq eat-term-terminfo-directory old-terminfo-path)
+ (setq eat-term-terminfo-directory eat--terminfo-path))
+ (when (eq eat-term-shell-integration-directory
+ old-shell-integration-path)
+ (setq eat-term-shell-integration-directory
+ eat--shell-integration-path)))
+
+(defcustom eat-term-inside-emacs (format "%s,eat" emacs-version)
+ "Value for the `INSIDE_EMACS' environment variable."
+ :type 'string
+ :group 'eat-term)
+
+(defcustom eat-enable-blinking-text nil
+ "Non-nil means enable blinking of text with blink attribute.
+
+When non-nil, enable `eat-blink-mode' to enable blinking of text with
+blink attribute by default. You manually toggle `eat-blink-mode' to
+toggle this behavior buffer-locally."
+ :type 'boolean
+ :group 'eat-ui
+ :group 'eat-eshell)
+
+(defcustom eat-slow-blink-frequency 2
+ "Frequency of blinking of slowly text.
+
+This has an effect only if `eat-blink-mode' is enabled."
+ :type 'number
+ :group 'eat-ui)
+
+(defcustom eat-fast-blink-frequency 3
+ "Frequency of blinking of rapidly text.
+
+This has an effect only if `eat-blink-mode' is enabled."
+ :type 'number
+ :group 'eat-ui)
+
+(defcustom eat-enable-alternative-display t
+ "Non-nil means enable alternative display.
+
+Full screen programs often use alternative display to keep old
+contents on display unaltered."
+ :type 'boolean
+ :group 'eat-term)
+
+(make-obsolete-variable 'eat-enable-alternative-display
+ "don't use it." "0.9" 'set)
+
+(defcustom eat-enable-mouse t
+ "Non-nil means enable mouse support.
+
+When non-nil, terminal programs can receive mouse events from Emacs."
+ :type 'boolean
+ :group 'eat-ui)
+
+(defcustom eat-input-chunk-size 1024
+ "Maximum size of chunk of data send at once.
+
+Long inputs send to Eat processes are broken up into chunks of this
+size.
+
+If your process is choking on big inputs, try lowering the value."
+ :type 'integer
+ :group 'eat-ui)
+
+(defface eat-term-bold '((t :inherit bold))
+ "Face used to render bold text."
+ :group 'eat-term)
+
+(defface eat-term-faint '((t :weight light))
+ "Face used to render faint text."
+ :group 'eat-term)
+
+(defface eat-term-italic '((t :inherit italic))
+ "Face used to render italic text."
+ :group 'eat-term)
+
+(defface eat-term-slow-blink '((t :inverse-video t))
+ "Face used to render slowly blinking text."
+ :group 'eat-term)
+
+(defface eat-term-fast-blink '((t :inverse-video t))
+ "Face used to render rapidly blinking text."
+ :group 'eat-term)
+
+;; Define color faces.
+(let ((face-counter 0))
+ (let ((colors '("black" "red" "green" "yellow" "blue" "magenta"
+ "cyan" "white")))
+ ;; Basic colors.
+ (dolist (color colors)
+ (let ((face (intern (format "eat-term-color-%i" face-counter))))
+ (custom-declare-face
+ face `((t :inherit
+ ,(intern (format (if (eval-when-compile
+ (>= emacs-major-version 28))
+ "ansi-color-%s"
+ "term-color-%s")
+ color))))
+ (format "Face used to render %s color text." color)
+ :group 'eat-term)
+ (put (intern (format "eat-term-color-%s" color))
+ 'face-alias face))
+ (cl-incf face-counter))
+ ;; Bright colors.
+ (dolist (color colors)
+ (let ((face (intern (format "eat-term-color-%i" face-counter))))
+ (custom-declare-face
+ face `((t :inherit
+ ,(intern (format (if (eval-when-compile
+ (>= emacs-major-version 28))
+ "ansi-color-bright-%s"
+ "term-color-%s")
+ color))))
+ (format "Face used to render bright %s color text." color)
+ :group 'eat-term)
+ (put (intern (format "eat-term-color-bright-%s" color))
+ 'face-alias face))
+ (cl-incf face-counter)))
+ ;; 256-colors.
+ (while (< face-counter 256)
+ (let ((color
+ (if (>= face-counter 232)
+ (format "#%06X"
+ (* #x010101
+ (+ 8 (* 10 (- face-counter 232)))))
+ (let ((col (- face-counter 16))
+ (res 0)
+ (frac (* 6 6)))
+ (while (<= 1 frac)
+ (setq res (* res #x000100))
+ (let ((color-num (mod (/ col frac) 6)))
+ (unless (zerop color-num)
+ (setq res (+ res #x37 (* #x28 color-num)))))
+ (setq frac (/ frac 6)))
+ (format "#%06X" res)))))
+ (custom-declare-face
+ (intern (format "eat-term-color-%i" face-counter))
+ `((t :foreground ,color :background ,color))
+ (format "Face used to render text with %i%s color of 256 color\
+ palette."
+ face-counter
+ (or (and (not (<= 11 (% face-counter 100) 13))
+ (nth (% face-counter 10)
+ '(nil "st" "nd" "rd")))
+ "th"))
+ :group 'eat-term))
+ (cl-incf face-counter)))
+
+(defface eat-term-font-0 '((t))
+ "Default font."
+ :group 'eat-term)
+
+(put 'eat-term-font-default 'face-alias 'eat-term-font-0)
+
+;; Font faces, 1 to 9 (inclusive).
+(cl-loop for counter from 1 to 9
+ do (custom-declare-face
+ (intern (format "eat-term-font-%i" counter)) '((t))
+ (format "Alternative font %i." counter)
+ :group 'eat-term))
+
+\f
+;;;; Utility Functions.
+
+(defun eat--t-goto-bol (&optional n)
+ "Go to the beginning of current line.
+
+With optional argument N, go to the beginning of Nth next line if N is
+positive, otherwise go to the beginning of -Nth previous line. If the
+specified position is before `point-min' or after `point-max', go to
+that point.
+
+Return the number of lines moved.
+
+Treat LINE FEED (?\\n) as the line delimiter."
+ ;; TODO: Comment.
+ (setq n (or n 0))
+ (cond ((> n 0)
+ (let ((moved 0))
+ (while (and (< (point) (point-max))
+ (< moved n))
+ (and (search-forward "\n" nil 'move)
+ (cl-incf moved)))
+ moved))
+ ((<= n 0)
+ (let ((moved 1))
+ (while (and (or (= moved 1)
+ (< (point-min) (point)))
+ (< n moved))
+ (cl-decf moved)
+ (and (search-backward "\n" nil 'move)
+ (= moved n)
+ (goto-char (match-end 0))))
+ moved))))
+
+(defun eat--t-goto-eol (&optional n)
+ "Go to the end of current line.
+
+With optional argument N, go to the end of Nth next line if N is
+positive, otherwise go to the end of -Nth previous line. If the
+specified position is before `point-min' or after `point-max', go to
+that point.
+
+Return the number of lines moved.
+
+Treat LINE FEED (?\\n) as the line delimiter."
+ ;; TODO: Comment.
+ (setq n (or n 0))
+ (cond ((>= n 0)
+ (let ((moved -1))
+ (while (and (or (= moved -1)
+ (< (point) (point-max)))
+ (< moved n))
+ (cl-incf moved)
+ (and (search-forward "\n" nil 'move)
+ (= moved n)
+ (goto-char (match-beginning 0))))
+ moved))
+ ((< n 0)
+ (let ((moved 0))
+ (while (and (< (point-min) (point))
+ (< n moved))
+ (and (search-backward "\n" nil 'move)
+ (cl-decf moved)))
+ moved))))
+
+(defun eat--t-bol (&optional n)
+ "Return the beginning of current line.
+
+With optional argument N, return a cons cell whose car is the
+beginning of Nth next line and cdr is N, if N is positive, otherwise
+return a cons cell whose car is the beginning of -Nth previous line
+and cdr is N. If the specified position is before `point-min' or
+after `point-max', return a cons cell whose car is that point and cdr
+is number of lines that point is away from current line.
+
+Treat LINE FEED (?\\n) as the line delimiter."
+ ;; Move to the beginning of line, record the point, and return that
+ ;; point and the distance of that point from current line in lines.
+ (save-excursion
+ ;; `let' is neccessary, we need to evaluate (point) after going to
+ ;; `(eat--t-goto-bol N)'.
+ (let ((moved (eat--t-goto-bol n)))
+ (cons (point) moved))))
+
+(defun eat--t-eol (&optional n)
+ "Return the end of current line.
+
+With optional argument N, return a cons cell whose car the end of Nth
+next line and cdr is N, if N is positive, otherwise return a cons cell
+whose car is the end of -Nth previous line and cdr in N. If the
+specified position is before `point-min' or after `point-max', return
+a cons cell whose car is that point and cdr is number of lines that
+point is away from current line.
+
+Treat LINE FEED (?\\n) as the line delimiter."
+ ;; Move to the beginning of line, record the point, and return that
+ ;; point and the distance of that point from current line in lines.
+ (save-excursion
+ ;; `let' is neccessary, we need to evaluate (point) after going to
+ ;; (eat--t-goto-eol N).
+ (let ((moved (eat--t-goto-eol n)))
+ (cons (point) moved))))
+
+(defun eat--t-col-motion (n)
+ "Move to Nth next column.
+
+Go to Nth next column if N is positive, otherwise go to -Nth previous
+column. If the specified position is before `point-min' or after
+`point-max', go to that point.
+
+Return the number of columns moved.
+
+Assume all characters occupy a single column."
+ ;; Record the current position.
+ (let ((start-pos (point)))
+ ;; Move to the new position.
+ (cond ((> n 0)
+ (let ((eol (car (eat--t-eol)))
+ (pos (+ (point) n)))
+ (goto-char (min pos eol))))
+ ((< n 0)
+ (let ((bol (car (eat--t-bol)))
+ (pos (+ (point) n)))
+ (goto-char (max pos bol)))))
+ ;; Return the distance from the previous position.
+ (- (point) start-pos)))
+
+(defun eat--t-current-col ()
+ "Return the current column.
+
+Assume all characters occupy a single column."
+ ;; We assume that that all characters occupy a single column, so a
+ ;; subtraction should work. For multi-column characters, we add
+ ;; extra invisible spaces before the character to make it occupy as
+ ;; many character is its width.
+ (- (point) (car (eat--t-bol))))
+
+(defun eat--t-goto-col (n)
+ "Go to column N.
+
+Return the current column after moving point.
+
+Assume all characters occupy a single column."
+ ;; Move to column 0.
+ (eat--t-goto-bol)
+ ;; Now the target column is N characters away.
+ (eat--t-col-motion n))
+
+(defun eat--t-repeated-insert (c n &optional face)
+ "Insert character C, N times, using face FACE, if given."
+ (insert (if face
+ (let ((str (make-string n c)))
+ (put-text-property 0 n 'face face str)
+ (put-text-property 0 n 'font-lock-face face str)
+ str)
+ ;; Avoid the `let'.
+ (make-string n c))))
+
+(defun eat--t-join-long-line (&optional limit)
+ "Join long line once, but don't try to go beyond LIMIT.
+
+For example: \"*foo\\nbar\\nbaz\" is converted to \"foo*bar\\nbaz\",
+where `*' indicates point."
+ ;; Are we already at the end a part of a long line?
+ (unless (get-text-property (point) 'eat--t-wrap-line)
+ ;; Find the next end of a part of a long line.
+ (goto-char (or (next-single-property-change
+ (point) 'eat--t-wrap-line nil limit)
+ limit (point-max))))
+ ;; Remove the newline.
+ (when (< (point) (or limit (point-max)))
+ (1value (cl-assert (1value (= (1value (char-after)) ?\n))))
+ (delete-char 1)))
+
+(defun eat--t-break-long-line (threshold)
+ "Break a line longer than THRESHOLD once.
+
+For example: when THRESHOLD is 3, \"*foobarbaz\" is converted to
+\"foo\\n*barbaz\", where `*' indicates point."
+ (let ((loop t))
+ ;; Find a too long line.
+ (while (and loop (< (point) (point-max)))
+ ;; Go to the threshold column.
+ (eat--t-goto-col threshold)
+ ;; Are we at the end of line?
+ (if (eq (char-after) ?\n)
+ ;; We are already at the end of line, so move to the next
+ ;; line and start from the beginning.
+ (forward-char)
+ ;; The next character is not a newline, so we must be at a
+ ;; long line, or we are the end of the accessible part of the
+ ;; buffer. Whatever the case, we break the loop, and if it is
+ ;; a long line, we break the line.
+ (setq loop nil)
+ (unless (= (point) (point-max))
+ (insert-before-markers
+ #("\n" 0 1 (eat--t-wrap-line t))))))))
+
+\f
+;;;; Emulator.
+
+(cl-defstruct (eat--t-cur
+ (:constructor eat--t-make-cur)
+ (:copier eat--t-copy-cur))
+ "Structure describing cursor position."
+ (position nil :documentation "Position of cursor.")
+ (y 1 :documentation "Y coordinate of cursor.")
+ (x 1 :documentation "X coordinate of cursor.")
+ (sixel-x 0 :documentation "X coordinate of Sixel cursor.")
+ (sixel-y 0 :documentation "Y coordinate of Sixel cursor.")
+ (sixel-beg nil :documentation "Cons cell of current sixel line."))
+
+(cl-defstruct (eat--t-disp
+ (:constructor eat--t-make-disp)
+ (:copier eat--t-copy-disp))
+ "Structure describing the display."
+ (begin nil :documentation "Beginning of visible display.")
+ (width 80 :documentation "Width of display.")
+ (height 24 :documentation "Height of display.")
+ (cursor nil :documentation "Cursor.")
+ (saved-cursor
+ (1value (eat--t-make-cur))
+ :documentation "Saved cursor.")
+ (old-begin
+ nil
+ :documentation
+ "Beginning of visible display during last Eat redisplay."))
+
+(cl-defstruct (eat--t-face
+ (:constructor eat--t-make-face)
+ (:copier eat--t-copy-face))
+ "Structure describing the display attributes to use."
+ (face nil :documentation "Face to use.")
+ (fg nil :documentation "Foreground color.")
+ (bg nil :documentation "Background color.")
+ (intensity nil :documentation "Intensity face, or nil.")
+ (italic nil :documentation "Non-nil means use italic face.")
+ (underline nil :documentation "Non-nil means underline text.")
+ (underline-color nil :documentation "Underline color.")
+ (crossed nil :documentation "Non-nil means strike-through text.")
+ (conceal nil :documentation "Non-nil means invisible text.")
+ (inverse nil :documentation "Non-nil means inverse colors.")
+ (blink nil :documentation "Blink face, or nil.")
+ (font 'eat-term-font-0 :documentation "Current font face."))
+
+(cl-defstruct (eat--t-term
+ (:constructor eat--t-make-term)
+ (:copier eat--t-copy-term))
+ "Structure describing a terminal."
+ (buffer nil :documentation "The buffer of terminal.")
+ (begin nil :documentation "Beginning of terminal.")
+ (end nil :documentation "End of terminal area.")
+ (title "" :documentation "The title of the terminal.")
+ (bell-fn
+ (1value #'ignore)
+ :documentation "Function to ring the bell.")
+ (input-fn
+ (1value #'ignore)
+ :documentation "Function to send input.")
+ (set-cursor-fn
+ (1value #'ignore)
+ :documentation "Function to set cursor.")
+ (manipulate-selection-fn
+ (1value #'ignore)
+ :documentation "Function to manipulate selection.")
+ (grab-mouse-fn
+ (1value #'ignore)
+ :documentation "Function to grab mouse.")
+ (set-focus-ev-mode-fn
+ (1value #'ignore)
+ :documentation "Function to set focus event mode.")
+ (set-title-fn
+ (1value #'ignore)
+ :documentation "Function to set the title.")
+ (set-cwd-fn
+ (1value #'ignore)
+ :documentation "Function to set the current working directory.")
+ (ui-cmd-fn
+ (1value #'ignore)
+ :documentation "Function to handle UI command sequence.")
+ (parser-state nil :documentation "State of parser.")
+ (scroll-begin 1 :documentation "First line of scroll region.")
+ (scroll-end 24 :documentation "Last line of scroll region.")
+ (display nil :documentation "The display.")
+ (main-display nil :documentation "Main display.
+
+Nil when not in alternative display mode.")
+ (face
+ (1value (eat--t-make-face))
+ :documentation "Display attributes.")
+ (auto-margin t :documentation "State of auto margin mode.")
+ (ins-mode nil :documentation "State of insert mode.")
+ (charset
+ (copy-tree '(g0 . ((g0 . us-ascii)
+ (g1 . us-ascii)
+ (g2 . us-ascii)
+ (g3 . us-ascii))))
+ :documentation "Current character set.")
+ (cur-state :block :documentation "Current state of cursor.")
+ (cur-visible-p t :documentation "Is the cursor visible?")
+ (saved-face
+ (1value (eat--t-make-face))
+ :documentation "Saved SGR attributes.")
+ (bracketed-yank nil :documentation "State of bracketed yank mode.")
+ (keypad-mode nil :documentation "State of keypad mode.")
+ (mouse-mode nil :documentation "Current mouse mode.")
+ (mouse-pressed nil :documentation "Pressed mouse buttons.")
+ (mouse-encoding nil :documentation "Current mouse event encoding.")
+ (focus-event-mode nil :documentation "Whether to send focus event.")
+ (cut-buffers
+ (1value (make-vector 8 nil))
+ :documentation "Cut buffers.")
+ (sixel-buffer
+ (let ((pair (cons (cons 0 (make-vector 1000 nil)) nil)))
+ (setf (cdr pair) (cons pair pair))
+ pair)
+ :documentation "Buffer to hold Sixel data.")
+ (sixel-buffer-size 1 :documentation "Line count in Sixel buffer.")
+ (sixel-palette
+ (copy-sequence (make-vector 256 nil))
+ :documentation "Sixel color registers.")
+ (sixel-color 0 :documentation "Current Sixel color register.")
+ (sixel-render-format
+ 'background
+ :documentation "Format to render Sixel images in.")
+ (sixel-image-extra-props
+ nil
+ :documentation "Extra properties of images used to display Sixel.")
+ (sixel-scroll-mode t :documentation "Whether to auto-scroll.")
+ (sixel-initial-cursor-pos
+ '(1 . 1)
+ :documentation "Initial position of cursor before entering Sixel.")
+ (char-width 1 :documentation "Width of each character in pixel.")
+ (char-height 1 :documentation "Height of each character in pixel.")
+ ;; NOTE: Change the default value of parameters when changing this.
+ (bold-face 'eat-term-bold :documentation "Face for bold text.")
+ (faint-face 'eat-term-faint :documentation "Face for faint text.")
+ (italic-face 'eat-term-italic :documentation "Face for slant text.")
+ (slow-blink-face 'eat-term-slow-blink :documentation "Slow blink.")
+ (fast-blink-face 'eat-term-fast-blink :documentation "Fast blink.")
+ (color-faces
+ (copy-sequence
+ (eval-when-compile
+ (vconcat
+ (cl-loop for i from 0 to 255
+ collect (intern (format "eat-term-color-%i" i))))))
+ :documentation "Faces for colors.")
+ (font-faces
+ (copy-sequence
+ (eval-when-compile
+ (vconcat
+ (cl-loop for i from 0 to 9
+ collect (intern (format "eat-term-font-%i" i))))))
+ :documentation "Faces for fonts.")
+ (params
+ (copy-hash-table
+ (eval-when-compile
+ (let ((tbl (make-hash-table :test 'eq)))
+ (puthash 'input-function #'ignore tbl)
+ (puthash 'ring-bell-function #'ignore tbl)
+ (puthash 'set-cursor-function #'ignore tbl)
+ (puthash 'grab-mouse-function #'ignore tbl)
+ (puthash 'grab-focus-events-function #'ignore tbl)
+ (puthash 'manipulate-selection-function #'ignore tbl)
+ (puthash 'set-title-function #'ignore tbl)
+ (puthash 'set-cwd-function #'ignore tbl)
+ (puthash 'ui-command-function #'ignore tbl)
+ (puthash 'char-dimensions '(1 . 1) tbl)
+ (puthash 'sixel-render-format 'background tbl)
+ (puthash 'bold-face 'eat-term-bold tbl)
+ (puthash 'faint-face 'eat-term-faint tbl)
+ (puthash 'italic-face 'eat-term-italic tbl)
+ (puthash 'slow-blink-face 'eat-term-slow-blink tbl)
+ (puthash 'fast-blink-face 'eat-term-fast-blink tbl)
+ (cl-loop
+ for i from 0 to 255
+ do (puthash (intern (format "color-%i-face" i))
+ (intern (format "eat-term-color-%i" i)) tbl))
+ (cl-loop
+ for i from 0 to 9
+ do (puthash (intern (format "font-%i-face" i))
+ (intern (format "eat-term-font-%i" i)) tbl))
+ tbl)))
+ :documentation "Alist of terminal parameters."))
+
+(defvar eat--t-term nil
+ "The current terminal.
+
+Don't `set' it, bind it to a value with `let'.")
+
+(defun eat--t-reset ()
+ "Reset terminal."
+ (let ((disp (eat--t-term-display eat--t-term)))
+ ;; Reset most of the things to their respective default values.
+ (setf (eat--t-term-parser-state eat--t-term) nil)
+ (setf (eat--t-disp-begin disp) (point-min-marker))
+ (setf (eat--t-disp-old-begin disp) (point-min-marker))
+ (setf (eat--t-disp-cursor disp)
+ (eat--t-make-cur :position (point-min-marker)))
+ (setf (eat--t-disp-saved-cursor disp) (eat--t-make-cur))
+ (setf (eat--t-term-scroll-begin eat--t-term) 1)
+ (setf (eat--t-term-scroll-end eat--t-term)
+ (eat--t-disp-height disp))
+ (setf (eat--t-term-main-display eat--t-term) nil)
+ (setf (eat--t-term-face eat--t-term) (eat--t-make-face))
+ (setf (eat--t-term-auto-margin eat--t-term) t)
+ (setf (eat--t-term-ins-mode eat--t-term) nil)
+ (setf (eat--t-term-charset eat--t-term)
+ '(g0 (g0 . us-ascii)
+ (g1 . dec-line-drawing)
+ (g2 . dec-line-drawing)
+ (g3 . dec-line-drawing)))
+ (setf (eat--t-term-saved-face eat--t-term) (eat--t-make-face))
+ (setf (eat--t-term-bracketed-yank eat--t-term) nil)
+ (setf (eat--t-term-cur-state eat--t-term) :block)
+ (setf (eat--t-term-cur-visible-p eat--t-term) t)
+ (setf (eat--t-term-title eat--t-term) "")
+ (setf (eat--t-term-keypad-mode eat--t-term) nil)
+ (setf (eat--t-term-mouse-mode eat--t-term) nil)
+ (setf (eat--t-term-mouse-encoding eat--t-term) nil)
+ (setf (eat--t-term-focus-event-mode eat--t-term) nil)
+ (setf (eat--t-term-sixel-scroll-mode eat--t-term) t)
+ ;; Clear everything.
+ (delete-region (point-min) (point-max))
+ ;; Inform the UI about our new state.
+ (funcall (eat--t-term-grab-mouse-fn eat--t-term) eat--t-term nil)
+ (funcall (eat--t-term-set-focus-ev-mode-fn eat--t-term)
+ eat--t-term nil)
+ (funcall (eat--t-term-set-title-fn eat--t-term) eat--t-term "")
+ (funcall (eat--t-term-set-cursor-fn eat--t-term) eat--t-term
+ :block)))
+
+(defun eat--t-cur-right (&optional n)
+ "Move cursor N columns right.
+
+N default to 1. If N is out of range, place cursor at the edge of
+display."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; If N is less than 1, set N to 1. If N is more than the number
+ ;; of available columns on the right side, set N to the maximum
+ ;; possible value.
+ (setq n (min (- (eat--t-disp-width disp) (eat--t-cur-x cursor))
+ (max (or n 1) 1)))
+ ;; N is non-zero in most cases, except at the edge of display.
+ (unless (zerop n)
+ ;; Move to the Nth next column, use spaces to reach that column
+ ;; if needed.
+ (eat--t-repeated-insert ?\s (- n (eat--t-col-motion n)))
+ (cl-incf (eat--t-cur-x cursor) n))))
+
+(defun eat--t-cur-left (&optional n)
+ "Move cursor N columns left.
+
+N default to 1. If N is out of range, place cursor at the edge of
+display."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; If N is less than 1, set N to 1. If N is more than the number
+ ;; of available columns on the left side, set N to the maximum
+ ;; possible value.
+ (setq n (min (1- (eat--t-cur-x cursor)) (max (or n 1) 1)))
+ ;; N is non-zero in most cases, except at the edge of display.
+ (unless (zerop n)
+ ;; Move to the Nth previous column.
+ (cl-assert (1value (>= (eat--t-current-col) n)))
+ (backward-char n)
+ (cl-decf (eat--t-cur-x cursor) n))))
+
+(defun eat--t-cur-horizontal-abs (&optional n)
+ "Move cursor to Nth column on current line.
+
+N default to 1. If N is out of range, place cursor at the edge of
+display."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; If N is out of range, bring it within the bounds of range.
+ (setq n (min (max (or n 1) 1) (eat--t-disp-width disp)))
+ ;; Depending on the current position of cursor, move right or
+ ;; left.
+ (cond ((< (eat--t-cur-x cursor) n)
+ (eat--t-cur-right (- n (eat--t-cur-x cursor))))
+ ((< n (eat--t-cur-x cursor))
+ (eat--t-cur-left (- (eat--t-cur-x cursor) n))))))
+
+(defun eat--t-beg-of-next-line (n)
+ "Move to beginning of Nth next line."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; If N is less than 1, set N to 1. If N is more than the number
+ ;; of available lines below, set N to the maximum possible value.
+ (setq n (min (- (eat--t-disp-height disp) (eat--t-cur-y cursor))
+ (max (or n 1) 1)))
+ ;; N is non-zero in most cases, except at the edge of display.
+ ;; Whatever the case, we move to the beginning of line.
+ (if (zerop n)
+ (1value (eat--t-goto-bol))
+ ;; Move to the Nth next line, use newlines to reach that line if
+ ;; needed.
+ (eat--t-repeated-insert ?\n (- n (eat--t-goto-bol n)))
+ (cl-incf (eat--t-cur-y cursor) n))
+ (1value (setf (eat--t-cur-x cursor) 1))))
+
+(defun eat--t-beg-of-prev-line (n)
+ "Move to beginning of Nth previous line."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; If N is less than 1, set N to 1. If N is more than the number
+ ;; of available lines above, set N to the maximum possible value.
+ (setq n (min (1- (eat--t-cur-y cursor)) (max (or n 1) 1)))
+ ;; Move to the beginning Nth previous line. Even if there are no
+ ;; line above, move to the beginning of the line.
+ (eat--t-goto-bol (- n))
+ (cl-decf (eat--t-cur-y cursor) n)
+ (1value (setf (eat--t-cur-x cursor) 1))))
+
+(defun eat--t-cur-down (&optional n)
+ "Move cursor N lines down.
+
+N default to 1. If N is out of range, place cursor at the edge of
+display."
+ (let ((x (eat--t-cur-x (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term)))))
+ ;; Move to the beginning of target line.
+ (eat--t-beg-of-next-line n)
+ ;; If the cursor wasn't at column one, move the cursor to the
+ ;; cursor to that column.
+ (unless (= x 1)
+ (eat--t-cur-right (1- x)))))
+
+(defun eat--t-cur-up (&optional n)
+ "Move cursor N lines up.
+
+N default to 1. If N is out of range, place cursor at the edge of
+display."
+ (let ((x (eat--t-cur-x (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term)))))
+ ;; Move to the beginning of target line.
+ (eat--t-beg-of-prev-line n)
+ ;; If the cursor wasn't at column one, move the cursor to the
+ ;; cursor to that column.
+ (unless (= x 1)
+ (eat--t-cur-right (1- x)))))
+
+(defun eat--t-cur-vertical-abs (&optional n)
+ "Move cursor to Nth line on display.
+
+N default to 1. If N is out of range, place cursor at the edge of
+display."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; If N is out of range, bring it within the bounds of range.
+ (setq n (min (max (or n 1) 1) (eat--t-disp-height disp)))
+ ;; Depending on the current position of cursor, move downward or
+ ;; upward.
+ (cond ((< (eat--t-cur-y cursor) n)
+ (eat--t-cur-down (- n (eat--t-cur-y cursor))))
+ ((< n (eat--t-cur-y cursor))
+ (eat--t-cur-up (- (eat--t-cur-y cursor) n))))))
+
+(defun eat--t-scroll-up (&optional n as-side-effect)
+ "Scroll up N lines, preserving cursor position.
+
+N default to 1. By default, don't change current line and current
+column, but if AS-SIDE-EFFECT is given and non-nil, assume that
+scrolling is triggered as a side effect of some other control function
+and don't move the point relative to the text and change current line
+accordingly."
+ (let ((disp (eat--t-term-display eat--t-term))
+ (scroll-begin (eat--t-term-scroll-begin eat--t-term))
+ (scroll-end (eat--t-term-scroll-end eat--t-term)))
+ ;; N shouldn't be more more than the number of lines in scroll
+ ;; region.
+ (setq n (min (max (or n 1) 0) (1+ (- scroll-end scroll-begin))))
+ ;; Make sure that N is positive.
+ (unless (zerop n)
+ ;; Try to not point relative to the text.
+ (save-excursion
+ (goto-char (eat--t-disp-begin disp))
+ ;; Move to the beginning of scroll region.
+ (eat--t-goto-bol (1- scroll-begin))
+ ;; If the first line on display isn't in scroll region or
+ ;; if this is the alternative display, delete text.
+ (if (or (eat--t-term-main-display eat--t-term)
+ (> scroll-begin 1))
+ (delete-region (point) (car (eat--t-bol n)))
+ ;; Otherwise, send the text to the scrollback area by
+ ;; advancing the display beginning marker.
+ (eat--t-goto-bol n)
+ ;; Make sure we're at the beginning of a line, because we
+ ;; might be at `point-max'.
+ (unless (or (= (point) (point-min))
+ (= (char-before) ?\n))
+ (insert ?\n))
+ (set-marker (eat--t-disp-begin disp) (point)))
+ ;; Is the last line on display in scroll region?
+ (when (< scroll-end (eat--t-disp-width disp))
+ ;; No, it isn't.
+ ;; Go to the end of scroll region (before deleting or moving
+ ;; texts).
+ (eat--t-goto-bol (- (1+ (- scroll-end scroll-begin)) n))
+ ;; If there is anything after the scroll region, insert
+ ;; newlines to keep that text unmoved.
+ (when (< (point) (point-max))
+ (eat--t-repeated-insert ?\n n))))
+ ;; Recalculate point if needed.
+ (let* ((cursor (eat--t-disp-cursor disp))
+ (recalc-point
+ (<= scroll-begin (eat--t-cur-y cursor) scroll-end)))
+ ;; If recalc-point is non-nil, and AS-SIDE-EFFECT is non-nil,
+ ;; update cursor position so that it is unmoved relative to
+ ;; surrounding text and reconsider point recalculation.
+ (when (and recalc-point as-side-effect)
+ (setq recalc-point (< (- (eat--t-cur-y cursor) n)
+ scroll-begin))
+ (setf (eat--t-cur-y cursor)
+ (max (- (eat--t-cur-y cursor) n) scroll-begin)))
+ (when recalc-point
+ ;; Recalculate point.
+ (let ((y (eat--t-cur-y cursor))
+ (x (eat--t-cur-x cursor)))
+ (eat--t-goto 1 1)
+ (eat--t-goto y x)))))))
+
+(defun eat--t-scroll-down (&optional n)
+ "Scroll down N lines, preserving cursor position.
+
+N defaults to 1."
+ (let ((disp (eat--t-term-display eat--t-term))
+ (scroll-begin (eat--t-term-scroll-begin eat--t-term))
+ (scroll-end (eat--t-term-scroll-end eat--t-term)))
+ ;; N shouldn't be more more than the number of lines in scroll
+ ;; region.
+ (setq n (min (max (or n 1) 0) (1+ (- scroll-end scroll-begin))))
+ ;; Make sure that N is positive.
+ (unless (zerop n)
+ ;; Move to the beginning of scroll region.
+ (goto-char (eat--t-disp-begin disp))
+ (eat--t-goto-bol (1- scroll-begin))
+ ;; Insert newlines to push text downwards.
+ (eat--t-repeated-insert ?\n n)
+ ;; Go to the end scroll region (after inserting newlines).
+ (eat--t-goto-eol (- (1+ (- scroll-end scroll-begin)) (1+ n)))
+ ;; Delete the text that was pushed out of scroll region.
+ (when (< (point) (point-max))
+ (delete-region (point) (car (eat--t-eol n))))
+ ;; The cursor mustn't move, so we have to recalculate point.
+ (let* ((cursor (eat--t-disp-cursor disp))
+ (y (eat--t-cur-y cursor))
+ (x (eat--t-cur-x cursor)))
+ (eat--t-goto 1 1)
+ (eat--t-goto y x)))))
+
+(defun eat--t-goto (&optional y x)
+ "Go to Xth column of Yth line of display.
+
+Y and X default to 1. Y and X are one-based. If Y and/or X are out
+of range, place cursor at the edge of display."
+ ;; Important special case: if Y and X are both one, move to the
+ ;; display beginning.
+ (if (and (or (not y) (eql y 1))
+ (or (not x) (eql x 1)))
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ (goto-char (eat--t-disp-begin disp))
+ (1value (setf (eat--t-cur-y cursor) 1
+ (eat--t-cur-x cursor) 1)))
+ ;; Move to column one, go to Yth line and move to Xth column.
+ ;; REVIEW: We move relative to cursor position, which faster for
+ ;; positions near the point (usually the case), but slower for
+ ;; positions far away from the point. There are only two cursor
+ ;; positions whose exact position is known beforehand, the cursor
+ ;; (whose position is (point)) and (1, 1) (the display beginning).
+ ;; There are almost always some points which are at more distance
+ ;; from current position than from the display beginning (the only
+ ;; exception is when the cursor is at the display beginning). So
+ ;; first moving to the display beginning and then moving to those
+ ;; point will be faster than moving from cursor (except a tiny
+ ;; (perhaps negligible) overhead of `goto-char'). What we don't
+ ;; have is a formula the calculate the distance between two
+ ;; positions.
+ (eat--t-cur-horizontal-abs 1)
+ (eat--t-cur-vertical-abs y)
+ (eat--t-cur-horizontal-abs x)))
+
+(defun eat--t-enable-auto-margin ()
+ "Enable automatic margin."
+ ;; Set the automatic margin flag to t, the rest of code will take
+ ;; care of the effects.
+ (1value (setf (eat--t-term-auto-margin eat--t-term) t)))
+
+(defun eat--t-disable-auto-margin ()
+ "Disable automatic margin."
+ ;; Set the automatic margin flag to nil, the rest of code will take
+ ;; care of the effects.
+ (1value (setf (eat--t-term-auto-margin eat--t-term) nil)))
+
+(defun eat--t-set-charset (slot charset)
+ "SLOT's character set to CHARSET."
+ (setf (alist-get slot (cdr (eat--t-term-charset eat--t-term)))
+ charset))
+
+(defun eat--t-change-charset (charset)
+ "Change character set to CHARSET.
+
+CHARSET should be one of `g0', `g1', `g2' and `g3'."
+ (cl-assert (memq charset '(g0 g1 g2 g3)))
+ (setf (car (eat--t-term-charset eat--t-term)) charset))
+
+(defun eat--t-move-before-to-safe ()
+ "Move to a safe position before point. Return how much moved.
+
+If the current position is safe, do nothing and return 0.
+
+Safe position is the position that's not on a multi-column wide
+character or its the internal invisible spaces."
+ (if (and (not (bobp))
+ ;; Is the current position unsafe?
+ (get-text-property (1- (point)) 'eat--t-invisible-space))
+ (let ((start-pos (point)))
+ ;; Move to the safe position.
+ (goto-char (or (previous-single-property-change
+ (point) 'eat--t-invisible-space)
+ (point-min)))
+ (cl-assert
+ (1value (or (bobp)
+ (null (get-text-property
+ (1- (point)) 'eat--t-invisible-space)))))
+ (- start-pos (point)))
+ 0))
+
+(defun eat--t-make-pos-safe ()
+ "If the position isn't safe, make it safe by replacing with spaces."
+ (let ((moved (eat--t-move-before-to-safe)))
+ (unless (zerop moved)
+ (let ((width (get-text-property
+ (point) 'eat--t-char-width)))
+ (cl-assert width)
+ (delete-region (point) (+ (point) width))
+ (eat--t-repeated-insert
+ ?\s width (eat--t-face-face
+ (eat--t-term-face eat--t-term)))
+ (backward-char (- width moved))))))
+
+(defun eat--t-fix-partial-multi-col-char (&optional preserve-face)
+ "Replace any partial multi-column character with spaces.
+
+If PRESERVE-FACE is non-nil, preserve original face."
+ (let ((face (if preserve-face
+ (get-char-property (point) 'face)
+ (eat--t-face-face
+ (eat--t-term-face eat--t-term)))))
+ (if (get-text-property (point) 'eat--t-invisible-space)
+ (let ((start-pos (point))
+ (count nil))
+ (goto-char (or (next-single-property-change
+ (point) 'eat--t-invisible-space)
+ (point-max)))
+ (setq count (- (1+ (point)) start-pos))
+ ;; Make sure we really overwrote the character
+ ;; partially.
+ (when (< count (get-text-property
+ (point) 'eat--t-char-width))
+ (delete-region start-pos (1+ (point)))
+ (eat--t-repeated-insert ?\s count face))
+ (goto-char start-pos))
+ ;; Detect the case where we have deleted all the invisible
+ ;; spaces before, but not the multi-column character itself.
+ (when-let* (((not (eobp)))
+ (w (get-text-property (point) 'eat--t-char-width))
+ ((> w 1)))
+ ;; `delete-char' also works, but it does more checks, so
+ ;; hopefully this will be faster.
+ (delete-region (point) (1+ (point)))
+ (insert (propertize " " 'face face 'font-lock-face face))
+ (backward-char)))))
+
+(defconst eat--t-dec-line-drawing-chars
+ (eval-and-compile
+ (let ((alist '((?+ . ?→)
+ (?, . ?←)
+ (?- . ?↑)
+ (?. . ?↓)
+ (?0 . ?█)
+ (?\` . ?�)
+ (?a . ?▒)
+ (?b . ?␉)
+ (?c . ?␌)
+ (?d . ?␍)
+ (?e . ?␊)
+ (?f . ?°)
+ (?g . ?±)
+ (?h . ?░)
+ (?i . ?#)
+ (?j . ?┘)
+ (?k . ?┐)
+ (?l . ?┌)
+ (?m . ?└)
+ (?n . ?┼)
+ (?o . ?⎺)
+ (?p . ?⎻)
+ (?q . ?─)
+ (?r . ?⎼)
+ (?s . ?⎽)
+ (?t . ?├)
+ (?u . ?┤)
+ (?v . ?┴)
+ (?w . ?┬)
+ (?x . ?│)
+ (?y . ?≤)
+ (?z . ?≥)
+ (?{ . ?π)
+ (?| . ?≠)
+ (?} . ?£)
+ (?~ . ?•)))
+ (table (make-hash-table :purecopy t)))
+ (dolist (pair alist)
+ (puthash (car pair) (cdr pair) table))
+ table))
+ "Hash table for DEC Line Drawing charset.
+
+The key is the output character from client, and value of the
+character to actually show.")
+
+(defun eat--t-write (str &optional beg end)
+ "Write STR from BEG to END on display."
+ (setq beg (or beg 0))
+ (setq end (or end (length str)))
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (scroll-end (eat--t-term-scroll-end eat--t-term))
+ (charset
+ (alist-get (car (eat--t-term-charset eat--t-term))
+ (cdr (eat--t-term-charset eat--t-term))))
+ (face (eat--t-face-face (eat--t-term-face eat--t-term)))
+ ;; Alist of indices and width of multi-column characters.
+ (multi-col-char-indices nil)
+ (inserted-till beg))
+ (cl-assert charset)
+ ;; Find all the multi-column wide characters in ST; hopefully it
+ ;; won't slow down showing plain ASCII.
+ (setq multi-col-char-indices
+ (cl-loop for i from beg to (1- end)
+ when (/= (char-width (aref str i)) 1)
+ collect (cons i (char-width (aref str i)))))
+ ;; If the position isn't safe, replace the multi-column
+ ;; character with spaces to make it safe.
+ (eat--t-make-pos-safe)
+ ;; TODO: Comment.
+ ;; REVIEW: This probably needs to be updated.
+ (while (< inserted-till end)
+ ;; Insert STR, and record the width of STR inserted
+ ;; successfully.
+ (let ((ins-count
+ (named-let write
+ ((max (min (- (eat--t-disp-width disp)
+ (1- (eat--t-cur-x cursor)))
+ (+ (- end inserted-till)
+ (cl-loop
+ for p in multi-col-char-indices
+ sum (1- (cdr p))))))
+ (written 0))
+ (let* ((next-multi-col (car multi-col-char-indices))
+ (end (+ inserted-till max))
+ (e (if next-multi-col
+ ;; Exclude the multi-column character.
+ (min (car next-multi-col) end)
+ end))
+ (wrote (- e inserted-till)))
+ (cl-assert (>= wrote 0))
+ (let ((s (substring str inserted-till e)))
+ ;; Convert STR to Unicode according to the
+ ;; current character set.
+ (pcase-exhaustive charset
+ ;; For `us-ascii', the default, no conversion
+ ;; is necessary.
+ ('us-ascii)
+ ;; `dec-line-drawing' contains various
+ ;; characters useful for drawing line diagram,
+ ;; so it is a must. This is also possible
+ ;; with `us-ascii', thanks to Unicode, but the
+ ;; character set `dec-line-drawing' is usually
+ ;; less expensive in terms of bytes needed to
+ ;; transfer than `us-ascii'.
+ ('dec-line-drawing
+ (dotimes (i (length s))
+ (when-let*
+ ((r (gethash
+ (aref s i)
+ eat--t-dec-line-drawing-chars)))
+ (aset s i r)))))
+ ;; Add face.
+ (put-text-property 0 (length s) 'face face s)
+ (put-text-property
+ 0 (length s) 'font-lock-face face s)
+ (insert s))
+ (setq inserted-till e)
+ (if (or (null next-multi-col)
+ (< (- end e) (cdr next-multi-col)))
+ ;; Either everything is done, or we reached
+ ;; the limit.
+ (+ written wrote)
+ ;; There are many characters which are too
+ ;; narrow for `char-width' to return 1. XTerm,
+ ;; Kitty and St seems to ignore them, so we too.
+ (if (zerop (cdr next-multi-col))
+ (cl-incf inserted-till)
+ (insert
+ ;; Make sure the multi-column character
+ ;; occupies the same number of characters as
+ ;; its width.
+ (propertize
+ (make-string (1- (cdr next-multi-col)) ?\s)
+ 'invisible t 'face face 'font-lock-face face
+ 'eat--t-invisible-space t
+ 'eat--t-char-width (cdr next-multi-col))
+ ;; Now insert the multi-column character.
+ (propertize
+ (substring str inserted-till
+ (cl-incf inserted-till))
+ 'face face 'font-lock-face face
+ 'eat--t-char-width (cdr next-multi-col))))
+ (setf multi-col-char-indices
+ (cdr multi-col-char-indices))
+ (write (- max wrote (cdr next-multi-col))
+ (+ written wrote
+ (cdr next-multi-col))))))))
+ (cl-incf (eat--t-cur-x cursor) ins-count)
+ (if (eat--t-term-ins-mode eat--t-term)
+ (delete-region
+ (save-excursion
+ (eat--t-col-motion (- (eat--t-disp-width disp)
+ (1- (eat--t-cur-x cursor))))
+ ;; Make sure the point is safe.
+ (eat--t-move-before-to-safe)
+ (point))
+ (car (eat--t-eol)))
+ (delete-region (point) (min (+ ins-count (point))
+ (car (eat--t-eol))))
+ ;; Replace any partially-overwritten character with
+ ;; spaces.
+ (eat--t-fix-partial-multi-col-char))
+ (when (> (eat--t-cur-x cursor) (eat--t-disp-width disp))
+ (if (not (eat--t-term-auto-margin eat--t-term))
+ (eat--t-cur-left 1)
+ (when (< inserted-till end)
+ (when (= (eat--t-cur-y cursor) scroll-end)
+ (eat--t-scroll-up 1 'as-side-effect))
+ (if (= (eat--t-cur-y cursor) scroll-end)
+ (eat--t-carriage-return)
+ (if (= (point) (point-max))
+ (insert #("\n" 0 1 (eat--t-wrap-line t)))
+ (put-text-property (point) (1+ (point))
+ 'eat--t-wrap-line t)
+ (forward-char))
+ (1value (setf (eat--t-cur-x cursor) 1))
+ (cl-incf (eat--t-cur-y cursor))))))))))
+
+(defun eat--t-horizontal-tab (&optional n)
+ "Go to the Nth next tabulation stop.
+
+N default to 1."
+ ;; N must be positive.
+ (setq n (max (or n 1) 1))
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Do some math calculate the distance of the Nth next tabulation
+ ;; stop from cursor, and go there.
+ (eat--t-cur-right (+ (- 8 (mod (1- (eat--t-cur-x cursor)) 8))
+ (* (1- n) 8)))))
+
+(defun eat--t-horizontal-backtab (&optional n)
+ "Go to the Nth previous tabulation stop.
+
+N default to 1."
+ ;; N must be positive.
+ (setq n (max (or n 1) 1))
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Do some math calculate the distance of the Nth next tabulation
+ ;; stop from cursor, and go there.
+ (eat--t-cur-left (+ (1+ (mod (- (eat--t-cur-x cursor) 2) 8))
+ (* (1- n) 8)))))
+
+(defun eat--t-index ()
+ "Go to the next line preserving column, scrolling if necessary."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (scroll-end (eat--t-term-scroll-end eat--t-term))
+ ;; Are we inside scroll region?
+ (in-scroll-region (<= (eat--t-cur-y cursor) scroll-end)))
+ ;; If this is the last line (of the scroll region or the display),
+ ;; scroll up, otherwise move cursor downward.
+ (if (= (if in-scroll-region scroll-end (eat--t-disp-height disp))
+ (eat--t-cur-y cursor))
+ (eat--t-scroll-up 1)
+ (eat--t-cur-down 1))))
+
+(defun eat--t-carriage-return ()
+ "Go to column one."
+ (eat--t-cur-horizontal-abs 1))
+
+(defun eat--t-line-feed ()
+ "Go to the first column of the next line, scrolling if necessary."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (scroll-end (eat--t-term-scroll-end eat--t-term))
+ ;; Are we inside scroll region?
+ (in-scroll-region (<= (eat--t-cur-y cursor) scroll-end)))
+ ;; If we are at the very end of the terminal, we might have some
+ ;; optimizations.
+ (if (= (point) (point-max))
+ ;; If the cursor is above the last line of the scroll region
+ ;; (or the display, if we are outside the scroll region), we
+ ;; can simply insert a newline and update the cursor position.
+ (if (/= (if in-scroll-region
+ scroll-end
+ (eat--t-disp-height disp))
+ (eat--t-cur-y cursor))
+ (progn
+ (insert ?\n)
+ (setf (eat--t-cur-x cursor) 1)
+ (cl-incf (eat--t-cur-y cursor)))
+ ;; This is the last line. We need to scroll up.
+ (eat--t-scroll-up 1 'as-side-effect)
+ ;; If we're still at the last line (only happens when the
+ ;; display has only a single line), go to column one of it.
+ (if (= (if in-scroll-region
+ scroll-end
+ (eat--t-disp-height disp))
+ (eat--t-cur-y cursor))
+ (eat--t-carriage-return)
+ ;; If we are somehow moved from the end of terminal,
+ ;; `eat--t-beg-of-next-line' is the best option.
+ (if (/= (point) (point-max))
+ (eat--t-beg-of-next-line 1)
+ ;; We are still at the end! We can can simply insert a
+ ;; newline and update the cursor position.
+ (insert ?\n)
+ (setf (eat--t-cur-x cursor) 1)
+ (cl-incf (eat--t-cur-y cursor)))))
+ ;; We are not at the end of terminal. But we still have a last
+ ;; chance. `eat--t-beg-of-next-line' is usually faster than
+ ;; `eat--t-carriage-return' followed by `eat--t-index', so if
+ ;; there is at least a single line (in the scroll region, if the
+ ;; cursor in the scroll region, otherwise in the display)
+ ;; underneath the cursor, we can use `eat--t-beg-of-next-line'.
+ (if (/= (if in-scroll-region
+ scroll-end
+ (eat--t-disp-height disp))
+ (eat--t-cur-y cursor))
+ (eat--t-beg-of-next-line 1)
+ ;; We don't have any other option, so we must use the most
+ ;; time-expensive option.
+ (eat--t-carriage-return)
+ (eat--t-index)))))
+
+(defun eat--t-reverse-index ()
+ "Go to the previous line preserving column, scrolling if needed."
+ (let* ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term)))
+ (scroll-begin (eat--t-term-scroll-begin eat--t-term))
+ ;; Are we in the scroll region?
+ (in-scroll-region (<= scroll-begin (eat--t-cur-y cursor))))
+ ;; If this is the first line (of the scroll region or the
+ ;; display), scroll down, otherwise move cursor upward.
+ (if (= (if in-scroll-region scroll-begin 1)
+ (eat--t-cur-y cursor))
+ (eat--t-scroll-down 1)
+ (eat--t-cur-up 1))))
+
+(defun eat--t-bell ()
+ "Ring the bell."
+ ;; Call the UI's bell handler.
+ (funcall (eat--t-term-bell-fn eat--t-term) eat--t-term))
+
+(defun eat--t-form-feed ()
+ "Insert a vertical tab."
+ ;; Form feed is same as `eat--t-index'.
+ (eat--t-index))
+
+(defun eat--t-save-cur ()
+ "Save current cursor position."
+ (let ((disp (eat--t-term-display eat--t-term))
+ (saved-face (eat--t-copy-face
+ (eat--t-term-face eat--t-term))))
+ ;; Save cursor position.
+ (setf (eat--t-disp-saved-cursor disp)
+ (eat--t-copy-cur (eat--t-disp-cursor disp)))
+ ;; Save SGR attributes.
+ (setf (eat--t-term-saved-face eat--t-term) saved-face)
+ ;; We use side-effects, so make sure the saved face doesn't share
+ ;; structure with the current face.
+ (setf (eat--t-face-face saved-face)
+ (copy-tree (eat--t-face-face saved-face)))
+ (setf (eat--t-face-underline-color saved-face)
+ (copy-tree (eat--t-face-underline-color saved-face)))))
+
+(defun eat--t-restore-cur ()
+ "Restore previously save cursor position."
+ (let ((saved (eat--t-disp-saved-cursor
+ (eat--t-term-display eat--t-term))))
+ ;; Restore cursor position.
+ (eat--t-goto (eat--t-cur-y saved) (eat--t-cur-x saved))
+ ;; Restore SGR attributes.
+ (setf (eat--t-term-face eat--t-term)
+ (copy-tree (eat--t-term-saved-face eat--t-term)))
+ (setf (eat--t-face-underline-color (eat--t-term-face eat--t-term))
+ (copy-tree (eat--t-face-underline-color
+ (eat--t-term-face eat--t-term))))))
+
+(defun eat--t-erase-in-line (&optional n)
+ "Erase part of current line, but don't move cursor.
+
+N defaults to 0. When N is 0, erase cursor to end of line. When N is
+1, erase beginning of line to cursor. When N is 2, erase whole line."
+ (let ((face (eat--t-term-face eat--t-term)))
+ (pcase-exhaustive n
+ ((or 0 'nil (pred (< 2)))
+ ;; Delete cursor position (inclusive) to end of line.
+ (delete-region (point) (car (eat--t-eol)))
+ ;; If the SGR background attribute is set, we need to fill the
+ ;; erased area with that background.
+ (when (eat--t-face-bg face)
+ (save-excursion
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ (eat--t-repeated-insert
+ ?\s (1+ (- (eat--t-disp-width disp)
+ (eat--t-cur-x cursor)))
+ (and (eat--t-face-bg face)
+ (eat--t-face-face face)))))))
+ (1
+ ;; Delete beginning of line to cursor position (inclusive).
+ (delete-region (car (eat--t-bol))
+ (if (or (= (point) (point-max))
+ (= (char-after) ?\n))
+ (point)
+ (1+ (point))))
+ ;; Fill the region with spaces, use SGR background attribute
+ ;; if set.
+ (let ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (eat--t-repeated-insert ?\s (eat--t-cur-x cursor)
+ (and (eat--t-face-bg face)
+ (eat--t-face-face face))))
+ ;; We erased the character at the cursor position, so after
+ ;; fill with spaces we are still off by one column; so move a
+ ;; column backward.
+ (backward-char))
+ (2
+ ;; Delete whole line.
+ (delete-region (car (eat--t-bol)) (car (eat--t-eol)))
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Fill the region before cursor position with spaces, use
+ ;; SGR background attribute if set.
+ (eat--t-repeated-insert ?\s (1- (eat--t-cur-x cursor))
+ (and (eat--t-face-bg face)
+ (eat--t-face-face face)))
+ ;; If the SGR background attribute is set, we need to fill
+ ;; the erased area including and after cursor position with
+ ;; that background.
+ (when (eat--t-face-bg face)
+ (save-excursion
+ (eat--t-repeated-insert
+ ?\s (1+ (- (eat--t-disp-width disp)
+ (eat--t-cur-x cursor)))
+ (and (eat--t-face-bg face)
+ (eat--t-face-face face))))))))))
+
+(defun eat--t-erase-in-disp (&optional n)
+ "Erase part of display.
+
+N defaults to 0. When N is 0, erase cursor to end of display. When N
+is 1, erase beginning of display to cursor. In both on the previous
+cases, don't move cursor. When N is 2, erase display and reset cursor
+to (1, 1). When N is 3, also erase the scrollback."
+ (let ((face (eat--t-term-face eat--t-term)))
+ (pcase-exhaustive n
+ ((or 0 'nil (pred (< 3)))
+ ;; Delete from cursor position (inclusive) to end of terminal.
+ (delete-region (point) (point-max))
+ ;; If the SGR background attribute is set, we need to fill the
+ ;; erased area with that background.
+ (when (eat--t-face-bg face)
+ ;; `save-excursion' probably uses marker to save point, which
+ ;; doesn't work in this case. So we the store the point as a
+ ;; integer.
+ (let* ((pos (point))
+ (disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Fill current line.
+ (eat--t-repeated-insert ?\s (1+ (- (eat--t-disp-width disp)
+ (eat--t-cur-x cursor)))
+ (eat--t-face-face face))
+ ;; Fill the following lines.
+ (dotimes (_ (- (eat--t-disp-height disp)
+ (eat--t-cur-y cursor)))
+ (insert ?\n)
+ (eat--t-repeated-insert ?\s (eat--t-disp-width disp)
+ (eat--t-face-face face)))
+ ;; Restore position.
+ (goto-char pos))))
+ (1
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (y (eat--t-cur-y cursor))
+ (x (eat--t-cur-x cursor))
+ ;; Should we erase including the cursor position?
+ (incl-point (/= (point) (point-max))))
+ ;; Delete the region to be erased.
+ (delete-region (eat--t-disp-begin disp)
+ (if incl-point (1+ (point)) (point)))
+ ;; If the SGR background attribute isn't set, insert
+ ;; newlines, otherwise fill the erased area above the current
+ ;; line with background color.
+ (if (not (eat--t-face-bg face))
+ (eat--t-repeated-insert ?\n (1- y))
+ (dotimes (_ (1- y))
+ (eat--t-repeated-insert ?\s (eat--t-disp-width disp)
+ (eat--t-face-face face))
+ (insert ?\n)))
+ ;; Fill the current line to keep the cursor unmoved. Use
+ ;; background if the corresponding SGR attribute is set.
+ (eat--t-repeated-insert ?\s x (and (eat--t-face-bg face)
+ (eat--t-face-face face)))
+ ;; We are off by one column; so move a column backward.
+ (when incl-point
+ (backward-char))))
+ ((or 2 3)
+ ;; Move to the display beginning.
+ (eat--t-goto 1 1)
+ ;; Delete everything in the display, and if N is 3, also delete
+ ;; everything in the scrollback area.
+ (delete-region (if (= n 2) (point) (point-min))
+ (point-max))
+ ;; If the SGR background attribute is set, fill the display
+ ;; with that background.
+ (when (eat--t-face-bg face)
+ ;; `save-excursion' probably uses marker to save point, which
+ ;; doesn't work in this case. So we the store the point as a
+ ;; integer.
+ (let ((pos (point))
+ (disp (eat--t-term-display eat--t-term)))
+ (dotimes (i (eat--t-disp-height disp))
+ (unless (zerop i)
+ (insert ?\n))
+ (eat--t-repeated-insert ?\s (eat--t-disp-width disp)
+ (eat--t-face-face face)))
+ ;; Restore point.
+ (goto-char pos)))))))
+
+(defun eat--t-device-status-report (n)
+ "Report device (terminal) status.
+
+If N is 5, send OK sequence. If N is 6, send the current Y and X
+coordinate to client."
+ (pcase n
+ (5
+ (funcall (eat--t-term-input-fn eat--t-term) eat--t-term "\e[0n"))
+ (6
+ (let ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (funcall (eat--t-term-input-fn eat--t-term) eat--t-term
+ (format "\e[%i;%iR" (eat--t-cur-y cursor)
+ (eat--t-cur-x cursor)))))))
+
+(defun eat--t-set-cursor-state (state)
+ "Set cursor state to STATE.
+
+STATE one of the `:invisible', `:block', `:blinking-block',
+`:underline', `:blinking-underline', `:bar', `:blinking-bar'."
+ (if (eq state :invisible)
+ (when (eat--t-term-cur-visible-p eat--t-term)
+ (setf (eat--t-term-cur-visible-p eat--t-term) nil)
+ (funcall (eat--t-term-set-cursor-fn eat--t-term) eat--t-term
+ :invisible))
+ (unless (and (eat--t-term-cur-visible-p eat--t-term)
+ (eq (eat--t-term-cur-state eat--t-term) state))
+ ;; Update state.
+ (setf (eat--t-term-cur-state eat--t-term) state)
+ (setf (eat--t-term-cur-visible-p eat--t-term) t)
+ ;; Inform the UI.
+ (funcall (eat--t-term-set-cursor-fn eat--t-term) eat--t-term
+ state))))
+
+(defun eat--t-set-cursor-style (style)
+ "Set cursor state as described by STYLE."
+ (when (<= 0 style 6)
+ (let ((state (aref [ :blinking-block :blinking-block :block
+ :blinking-underline :underline
+ :blinking-bar :bar]
+ style)))
+ (if (eat--t-term-cur-visible-p eat--t-term)
+ (eat--t-set-cursor-state state)
+ (setf (eat--t-term-cur-state eat--t-term) state)))))
+
+(defun eat--t-show-cursor ()
+ "Make the cursor visible."
+ (when (not (eat--t-term-cur-visible-p eat--t-term))
+ (eat--t-set-cursor-state (eat--t-term-cur-state eat--t-term))))
+
+(defun eat--t-hide-cursor ()
+ "Make the cursor invisible."
+ (when (eat--t-term-cur-visible-p eat--t-term)
+ (eat--t-set-cursor-state :invisible)))
+
+(defun eat--t-blinking-cursor ()
+ "Make the cursor blink."
+ (let ((state (pcase (eat--t-term-cur-state eat--t-term)
+ (:block :blinking-block)
+ (:underline :blinking-underline)
+ (:bar :blinking-bar)
+ (state state))))
+ (if (eat--t-term-cur-visible-p eat--t-term)
+ (eat--t-set-cursor-state state)
+ (setf (eat--t-term-cur-state eat--t-term) state))))
+
+(defun eat--t-non-blinking-cursor ()
+ "Make the cursor not blink."
+ (let ((state (pcase (eat--t-term-cur-state eat--t-term)
+ (:blinking-block :block)
+ (:blinking-underline :underline)
+ (:blinking-bar :bar)
+ (state state))))
+ (if (eat--t-term-cur-visible-p eat--t-term)
+ (eat--t-set-cursor-state state)
+ (setf (eat--t-term-cur-state eat--t-term) state))))
+
+(defun eat--t-enable-bracketed-yank ()
+ "Enable bracketed yank mode."
+ (setf (eat--t-term-bracketed-yank eat--t-term) t))
+
+(defun eat--t-disable-bracketed-yank ()
+ "Disable bracketed yank mode."
+ (setf (eat--t-term-bracketed-yank eat--t-term) nil))
+
+(defun eat--t-enable-alt-disp ()
+ "Enable alternative display."
+ ;; Effective only when alternative display is enabled by user.
+ (when eat-enable-alternative-display
+ ;; Make sure we not already in the alternative display.
+ (unless (eat--t-term-main-display eat--t-term)
+ ;; Store the current display, including scrollback.
+ (let ((main-disp (eat--t-copy-disp
+ (eat--t-term-display eat--t-term))))
+ (setf (eat--t-disp-begin main-disp)
+ (- (eat--t-disp-begin main-disp) (point-min)))
+ (setf (eat--t-disp-old-begin main-disp)
+ (- (eat--t-disp-old-begin main-disp) (point-min)))
+ (setf (eat--t-disp-cursor main-disp)
+ (eat--t-copy-cur (eat--t-disp-cursor main-disp)))
+ (setf (eat--t-disp-saved-cursor main-disp)
+ (eat--t-copy-cur (eat--t-disp-saved-cursor main-disp)))
+ (setf (eat--t-cur-position (eat--t-disp-cursor main-disp))
+ (- (point) (point-min)))
+ (setf (eat--t-term-main-display eat--t-term)
+ (cons main-disp (buffer-string)))
+ ;; Delete everything, and move to the beginning of terminal.
+ (delete-region (point-min) (point-max))
+ (eat--t-goto 1 1)))))
+
+(defun eat--t-disable-alt-disp (&optional dont-move-cursor)
+ "Disable alternative display.
+
+If DONT-MOVE-CURSOR is non-nil, don't move cursor from current
+position."
+ ;; Make sure we in the alternative display.
+ (when (eat--t-term-main-display eat--t-term)
+ (let ((main-disp (eat--t-term-main-display eat--t-term))
+ (old-y (eat--t-cur-y
+ (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (old-x (eat--t-cur-x
+ (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (width (eat--t-disp-width
+ (eat--t-term-display eat--t-term)))
+ (height (eat--t-disp-height
+ (eat--t-term-display eat--t-term))))
+ ;; Delete everything.
+ (delete-region (point-min) (point-max))
+ ;; Restore the main display.
+ (insert (cdr main-disp))
+ (setf (eat--t-cur-position (eat--t-disp-cursor (car main-disp)))
+ (copy-marker (+ (point-min)
+ (eat--t-cur-position
+ (eat--t-disp-cursor (car main-disp))))))
+ (setf (eat--t-disp-old-begin (car main-disp))
+ (copy-marker (+ (point-min)
+ (eat--t-disp-old-begin (car main-disp)))))
+ (setf (eat--t-disp-begin (car main-disp))
+ (copy-marker (+ (point-min)
+ (eat--t-disp-begin (car main-disp)))))
+ (setf (eat--t-term-display eat--t-term) (car main-disp)
+ (eat--t-term-main-display eat--t-term) nil)
+ (goto-char (eat--t-cur-position
+ (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ ;; Maybe the terminal was resized after enabling alternative
+ ;; display, so we have to resize again.
+ (eat--t-resize width height)
+ ;; Restore cursor position if DONT-MOVE-CURSOR is non-nil.
+ (when dont-move-cursor
+ (eat--t-goto old-y old-x)))))
+
+(defun eat--t-insert-char (n)
+ "Insert N empty (space) characters, preserving cursor."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Make sure N is positive. If N is more than the number of
+ ;; available columns available, set N to the maximum possible
+ ;; value.
+ (setq n (min (- (eat--t-disp-width disp)
+ (1- (eat--t-cur-x cursor)))
+ (max (or n 1) 1)))
+ ;; Return if N is zero.
+ (unless (zerop n)
+ ;; If the position isn't safe, replace the multi-column
+ ;; character with spaces to make it safe.
+ (eat--t-make-pos-safe)
+ (save-excursion
+ (let ((face (eat--t-term-face eat--t-term)))
+ ;; Insert N spaces, with SGR background if that attribute is
+ ;; set.
+ (eat--t-repeated-insert
+ ?\s n (and (eat--t-face-bg face) (eat--t-face-face face))))
+ ;; Remove the characters that went beyond the edge of
+ ;; display.
+ (eat--t-col-motion (- (eat--t-disp-width disp)
+ (+ (1- (eat--t-cur-x cursor)) n)))
+ ;; Make sure we delete any multi-column character
+ ;; completely.
+ (eat--t-move-before-to-safe)
+ (delete-region (point) (car (eat--t-eol)))))))
+
+(defun eat--t-delete-char (n)
+ "Delete N characters, preserving cursor."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (face (eat--t-term-face eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Make sure N is positive. If N is more than the number of
+ ;; available columns available, set N to the maximum possible
+ ;; value.
+ (setq n (min (- (eat--t-disp-width disp)
+ (1- (eat--t-cur-x cursor)))
+ (max (or n 1) 1)))
+ ;; Return if N is zero.
+ (unless (zerop n)
+ ;; If the position isn't safe, replace the multi-column
+ ;; character with spaces to make it safe.
+ (eat--t-make-pos-safe)
+ (save-excursion
+ (let ((m (point)))
+ ;; Delete N character on current line.
+ (eat--t-col-motion n)
+ (delete-region m (point))
+ ;; Replace any partially-overwritten character with spaces.
+ (eat--t-fix-partial-multi-col-char)
+ ;; If SGR background attribute is set, fill N characters at
+ ;; the right edge of display with that background.
+ (when (eat--t-face-bg face)
+ (save-excursion
+ (eat--t-goto-eol)
+ (let ((empty (1+ (- (eat--t-disp-width disp)
+ (eat--t-cur-x cursor)
+ (- (point) m)))))
+ ;; Reach the position from where to start filling.
+ ;; Use spaces if needed.
+ (when (> empty n)
+ (eat--t-repeated-insert ?\s (- empty n)))
+ ;; Fill with background.
+ (eat--t-repeated-insert
+ ?\s (min empty n) (eat--t-face-face face))))))))))
+
+(defun eat--t-erase-char (n)
+ "Make next N character cells empty, preserving cursor."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (face (eat--t-term-face eat--t-term))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; Make sure N is positive. If N is more than the number of
+ ;; available columns available, set N to the maximum possible
+ ;; value.
+ (setq n (min (- (eat--t-disp-width disp)
+ (1- (eat--t-cur-x cursor)))
+ (max (or n 1) 1)))
+ ;; Return if N is zero.
+ (unless (zerop n)
+ ;; If the position isn't safe, replace the multi-column
+ ;; character with spaces to make it safe.
+ (eat--t-make-pos-safe)
+ (save-excursion
+ (let ((m (point)))
+ ;; Delete N character on current line.
+ (eat--t-col-motion n)
+ (delete-region m (point))
+ ;; Replace any partially-overwritten character with spaces.
+ (eat--t-fix-partial-multi-col-char)
+ ;; Insert N spaces, with background if SGR background
+ ;; attribute is set.
+ (eat--t-repeated-insert
+ ?\s n (and (eat--t-face-bg face)
+ (eat--t-face-face face))))))))
+
+(defun eat--t-insert-line (n)
+ "Insert N empty lines, preserving cursor."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (scroll-begin (eat--t-term-scroll-begin eat--t-term))
+ (scroll-end (eat--t-term-scroll-end eat--t-term)))
+ ;; N should be positive and shouldn't exceed the number of lines
+ ;; below cursor position and inside current scroll region.
+ (setq n (min (- (1+ (- scroll-end scroll-begin))
+ (1- (eat--t-cur-y cursor)))
+ (max (or n 1) 1)))
+ ;; Make sure we are in the scroll region and N is positive, return
+ ;; on failure.
+ (when (and (<= scroll-begin (eat--t-cur-y cursor) scroll-end)
+ (not (zerop n)))
+ ;; This function doesn't move the cursor, but pushes all the
+ ;; line below and including current line. So to keep the cursor
+ ;; unmoved, go to the beginning of line and insert enough spaces
+ ;; to not move the cursor.
+ (eat--t-goto-bol)
+ (let ((face (eat--t-term-face eat--t-term)))
+ (eat--t-repeated-insert ?\s (1- (eat--t-cur-x cursor))
+ (and (eat--t-face-bg face)
+ (eat--t-face-face face)))
+ (goto-char
+ (prog1 (point)
+ ;; Insert N lines.
+ (if (not (eat--t-face-bg face))
+ (eat--t-repeated-insert ?\n n)
+ ;; SGR background attribute set, so fill the inserted
+ ;; lines with background.
+ (dotimes (i n)
+ ;; Fill a line.
+ (eat--t-repeated-insert
+ ?\s (if (not (zerop i))
+ (eat--t-disp-width disp)
+ ;; The first inserted line is already filled
+ ;; partially, so calculate the number columns
+ ;; left to fill.
+ (1+ (- (eat--t-disp-width disp)
+ (eat--t-cur-x cursor))))
+ (eat--t-face-face face))
+ ;; New line.
+ (insert ?\n)))
+ ;; Delete the lines that were just pushed beyond the end of
+ ;; scroll region.
+ (eat--t-goto-eol (- (1+ (- scroll-end scroll-begin))
+ (+ (- (eat--t-cur-y cursor)
+ (1- scroll-begin))
+ n)))
+ (delete-region (point) (car (eat--t-eol n)))))))))
+
+(defun eat--t-delete-line (n)
+ "Delete N lines, preserving cursor."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (x (eat--t-cur-x cursor))
+ (scroll-begin (eat--t-term-scroll-begin eat--t-term))
+ (scroll-end (eat--t-term-scroll-end eat--t-term)))
+ ;; N should be positive and shouldn't exceed the number of
+ ;; lines below cursor position and inside current scroll
+ ;; region.
+ (setq n (min (- (1+ (- scroll-end scroll-begin))
+ (1- (eat--t-cur-y cursor)))
+ (max (or n 1) 1)))
+ ;; Make sure we are in the scroll region and N is positive, return
+ ;; on failure.
+ (when (and (<= scroll-begin (eat--t-cur-y cursor) scroll-end)
+ (not (zerop n)))
+ ;; Delete N lines (including the current one).
+ (eat--t-goto-bol)
+ (save-excursion
+ (let ((m (point)))
+ (eat--t-goto-bol n)
+ (delete-region m (point))))
+ (let ((face (eat--t-term-face eat--t-term)))
+ ;; Keep the lines beyond end of scroll region unmoved.
+ (when (or (< scroll-end (eat--t-disp-height disp))
+ (eat--t-face-bg face))
+ (let* ((pos (point))
+ (move (- (1+ (- scroll-end scroll-begin))
+ (- (+ (eat--t-cur-y cursor) n)
+ (1- scroll-begin))))
+ (moved (eat--t-goto-eol move)))
+ (when (or (/= (point) (point-max))
+ (eat--t-face-bg face))
+ ;; Move to the end of scroll region.
+ (eat--t-repeated-insert ?\n (- move moved))
+ ;; Insert enough new lines, fill them when SGR
+ ;; background attribute is set.
+ (if (not (eat--t-face-bg face))
+ (eat--t-repeated-insert ?\n n)
+ (dotimes (_ n)
+ (insert ?\n)
+ (eat--t-repeated-insert ?\s (eat--t-disp-width disp)
+ (eat--t-face-face face)))))
+ (goto-char pos))))
+ ;; Go to column where cursor is to preserve cursor position, use
+ ;; spaces if needed to reach the position.
+ (eat--t-repeated-insert
+ ?\s (- (1- x) (eat--t-col-motion (1- x)))))))
+
+(defun eat--t-repeat-last-char (&optional n)
+ "Repeat last character N times."
+ ;; N must be at least one.
+ (setq n (max (or n 1) 1))
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (char
+ ;; Get the character before cursor.
+ (when (< (eat--t-disp-begin disp) (point))
+ (if (get-text-property (1- (point)) 'eat--t-wrap-line)
+ ;; The character before cursor is a newline to break
+ ;; a long line, so use the character before that.
+ (when (< (eat--t-disp-begin disp) (1- (point)))
+ (char-before (1- (point))))
+ (char-before)))))
+ ;; Insert `char' N times. Make sure `char' is a non-nil and not
+ ;; a newline.
+ (when (and char (/= char ?\n))
+ (eat--t-write (make-string n char)))))
+
+(defun eat--t-change-scroll-region (&optional top bottom)
+ "Change the scroll region from lines TOP to BOTTOM (inclusive).
+
+TOP defaults to 1 and BOTTOM defaults to the height of the display."
+ (let ((disp (eat--t-term-display eat--t-term)))
+ (setq top (or top 1))
+ (setq bottom (or bottom (eat--t-disp-height disp)))
+ ;; According to DEC's documentation (found somewhere on the
+ ;; internet, but can't remember where), TOP and BOTTOM must be
+ ;; within display, and BOTTOM must be below TOP. Otherwise the
+ ;; control function is a nop.
+ (when (< 0 top bottom (1+ (eat--t-disp-height disp)))
+ (setf (eat--t-term-scroll-begin eat--t-term) top
+ (eat--t-term-scroll-end eat--t-term) bottom)
+ (eat--t-goto 1 1))))
+
+(defun eat--t-insert-mode ()
+ "Enable insert mode and disable replace mode."
+ (setf (eat--t-term-ins-mode eat--t-term) t))
+
+(defun eat--t-replace-mode ()
+ "Enable replace mode and disable insert mode."
+ (setf (eat--t-term-ins-mode eat--t-term) nil))
+
+(defun eat--t-set-sgr-params (params)
+ "Set SGR parameters PARAMS."
+ (let ((face (eat--t-term-face eat--t-term)))
+ ;; Set attributes.
+ (while params
+ (pcase (pop params)
+ (`(,(or 0 'nil))
+ (1value (setf (eat--t-face-fg face) nil))
+ (1value (setf (eat--t-face-bg face) nil))
+ (1value (setf (eat--t-face-intensity face) nil))
+ (1value (setf (eat--t-face-italic face) nil))
+ (1value (setf (eat--t-face-underline face) nil))
+ (1value (setf (eat--t-face-underline-color face) nil))
+ (1value (setf (eat--t-face-crossed face) nil))
+ (1value (setf (eat--t-face-conceal face) nil))
+ (1value (setf (eat--t-face-inverse face) nil))
+ (1value (setf (eat--t-face-blink face) nil))
+ (setf (eat--t-face-font face)
+ (aref (eat--t-term-font-faces eat--t-term) 0)))
+ ('(1)
+ (setf (eat--t-face-intensity face)
+ (eat--t-term-bold-face eat--t-term)))
+ ('(2)
+ (setf (eat--t-face-intensity face)
+ (eat--t-term-faint-face eat--t-term)))
+ ('(3)
+ (setf (eat--t-face-italic face)
+ (eat--t-term-italic-face eat--t-term)))
+ ('(4)
+ (1value (setf (eat--t-face-underline face) 'line)))
+ ('(4 0)
+ (1value (setf (eat--t-face-underline face) nil)))
+ ('(4 1)
+ (1value (setf (eat--t-face-underline face) 'line)))
+ ('(4 2)
+ (1value (setf (eat--t-face-underline face) 'line)))
+ ('(4 3)
+ (1value (setf (eat--t-face-underline face) 'wave)))
+ ('(4 4)
+ (1value (setf (eat--t-face-underline face) 'wave)))
+ ('(4 5)
+ (1value (setf (eat--t-face-underline face) 'wave)))
+ ('(5)
+ (setf (eat--t-face-blink face)
+ (eat--t-term-slow-blink-face eat--t-term)))
+ ('(6)
+ (setf (eat--t-face-blink face)
+ (eat--t-term-fast-blink-face eat--t-term)))
+ ('(7)
+ (1value (setf (eat--t-face-inverse face) t)))
+ ('(8)
+ (1value (setf (eat--t-face-conceal face) t)))
+ ('(9)
+ (1value (setf (eat--t-face-crossed face) t)))
+ (`(,(and (pred (lambda (font) (<= 10 font 19)))
+ font))
+ (setf (eat--t-face-font face)
+ (aref (eat--t-term-font-faces eat--t-term)
+ (- font 10))))
+ ('(21)
+ (1value (setf (eat--t-face-underline face) 'line)))
+ ('(22)
+ (1value (setf (eat--t-face-intensity face) nil)))
+ ('(23)
+ (1value (setf (eat--t-face-italic face) nil)))
+ ('(24)
+ (1value (setf (eat--t-face-underline face) nil)))
+ ('(25)
+ (1value (setf (eat--t-face-blink face) nil)))
+ ('(27)
+ (1value (setf (eat--t-face-inverse face) nil)))
+ ('(28)
+ (1value (setf (eat--t-face-conceal face) nil)))
+ ('(29)
+ (1value (setf (eat--t-face-crossed face) nil)))
+ (`(,(and (pred (lambda (color) (<= 30 color 37)))
+ color))
+ (setf (eat--t-face-fg face)
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ (- color 30))
+ nil t)))
+ ('(38)
+ (pcase (pop params)
+ ('(2)
+ (setf (eat--t-face-fg face)
+ (let ((r (car (pop params)))
+ (g (car (pop params)))
+ (b (car (pop params))))
+ (when (and r (<= 0 r 255)
+ g (<= 0 g 255)
+ b (<= 0 b 255))
+ (format "#%02x%02x%02x" r g b)))))
+ ('(5)
+ (let ((color (car (pop params))))
+ (setf (eat--t-face-fg face)
+ (when (and color (<= 0 color 255))
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ color)
+ nil t)))))))
+ ('(39)
+ (1value (setf (eat--t-face-fg face) nil)))
+ (`(,(and (pred (lambda (color) (<= 40 color 47)))
+ color))
+ (setf (eat--t-face-bg face)
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ (- color 40))
+ nil t)))
+ ('(48)
+ (setf (eat--t-face-bg face)
+ (pcase (pop params)
+ ('(2)
+ (let ((r (car (pop params)))
+ (g (car (pop params)))
+ (b (car (pop params))))
+ (when (and r (<= 0 r 255)
+ g (<= 0 g 255)
+ b (<= 0 b 255))
+ (format "#%02x%02x%02x" r g b))))
+ ('(5)
+ (let ((color (car (pop params))))
+ (when (and color (<= 0 color 255))
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ color)
+ nil t)))))))
+ ('(49)
+ (1value (setf (eat--t-face-bg face) nil)))
+ ('(58)
+ (setf (eat--t-face-underline-color face)
+ (pcase (pop params)
+ ('(2)
+ (let ((r (car (pop params)))
+ (g (car (pop params)))
+ (b (car (pop params))))
+ (when (and r (<= 0 r 255)
+ g (<= 0 g 255)
+ b (<= 0 b 255))
+ (format "#%02x%02x%02x" r g b))))
+ ('(5)
+ (let ((color (car (pop params))))
+ (when (and color (<= 0 color 255))
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ color)
+ nil t)))))))
+ ('(59)
+ (1value (setf (eat--t-face-underline-color face) nil)))
+ (`(,(and (pred (lambda (color) (<= 90 color 97)))
+ color))
+ (setf (eat--t-face-fg face)
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ (- color 82))
+ nil t)))
+ (`(,(and (pred (lambda (color) (<= 100 color 107)))
+ color))
+ (setf (eat--t-face-bg face)
+ (face-foreground
+ (aref (eat--t-term-color-faces eat--t-term)
+ (- color 92))
+ nil t)))))
+ ;; Update face according to the attributes.
+ (setf (eat--t-face-face face)
+ `(,@(and-let* ((fg (or (if (eat--t-face-conceal face)
+ (eat--t-face-bg face)
+ (eat--t-face-fg face))
+ (cond
+ ((eat--t-face-inverse face)
+ (face-foreground 'default))
+ ((eat--t-face-conceal face)
+ (face-background 'default))))))
+ (list (if (eat--t-face-inverse face)
+ :background
+ :foreground)
+ fg))
+ ,@(and-let* ((bg (or (eat--t-face-bg face)
+ (and (eat--t-face-inverse face)
+ (face-background 'default)))))
+ (list (if (eat--t-face-inverse face)
+ :foreground
+ :background)
+ bg))
+ ,@(and-let* ((underline (eat--t-face-underline face)))
+ (list
+ :underline
+ (list :color (eat--t-face-underline-color face)
+ :style underline)))
+ ,@(and-let* ((crossed (eat--t-face-crossed face)))
+ ;; REVIEW: How about colors? No terminal supports
+ ;; crossed attribute with colors, so we'll need to be
+ ;; creative to add the feature.
+ `(:strike-through t))
+ :inherit
+ (,@(and-let* ((intensity (eat--t-face-intensity face)))
+ (list intensity))
+ ,@(and-let* ((italic (eat--t-face-italic face)))
+ (list italic))
+ ,@(and-let* ((blink (eat--t-face-blink face)))
+ (list blink))
+ ,(eat--t-face-font face))))))
+
+(defun eat--t-enable-keypad ()
+ "Enable keypad."
+ (1value (setf (eat--t-term-keypad-mode eat--t-term) t)))
+
+(defun eat--t-disable-keypad ()
+ "Disable keypad."
+ (1value (setf (eat--t-term-keypad-mode eat--t-term) nil)))
+
+(defun eat--t-enable-sgr-mouse-encoding ()
+ "Arrange that the following mouse events will be encoded like SGR."
+ (setf (eat--t-term-mouse-encoding eat--t-term) 'sgr))
+
+(defun eat--t-disable-sgr-mouse-encoding ()
+ "Arrange that the following mouse events won't be encoded like SGR."
+ (setf (eat--t-term-mouse-encoding eat--t-term) nil))
+
+(defun eat--t-set-mouse-mode (mode)
+ "Set current mouse mode to MODE.
+
+MODE should be one of nil and `x10', `normal', `button-event',
+`any-event'."
+ (setf (eat--t-term-mouse-mode eat--t-term) mode)
+ ;; When MODE is nil, disable mouse.
+ (unless mode
+ (eat--t-disable-sgr-mouse-encoding))
+ ;; `x10' mouse mode doesn't need to keep track of the mouse buttons
+ ;; pressed.
+ (when (or (not mode)
+ (eq mode 'x10))
+ (setf (eat--t-term-mouse-pressed eat--t-term) nil))
+ ;; Inform the UI.
+ (funcall (eat--t-term-grab-mouse-fn eat--t-term) eat--t-term
+ (pcase-exhaustive mode
+ ('x10 :click)
+ ('normal :modifier-click)
+ ('button-event :drag)
+ ('any-event :all)
+ ('nil nil))))
+
+(defun eat--t-enable-x10-mouse ()
+ "Enable X10 mouse tracking."
+ (eat--t-set-mouse-mode 'x10))
+
+(defun eat--t-enable-normal-mouse ()
+ "Enable normal mouse tracking."
+ (eat--t-set-mouse-mode 'normal))
+
+(defun eat--t-enable-button-event-mouse ()
+ "Enable button-event mouse tracking."
+ (eat--t-set-mouse-mode 'button-event))
+
+(defun eat--t-enable-any-event-mouse ()
+ "Enable any-event mouse tracking."
+ (eat--t-set-mouse-mode 'any-event))
+
+(defun eat--t-disable-mouse ()
+ "Disable mouse tracking."
+ (eat--t-set-mouse-mode nil))
+
+(defun eat--t-enable-focus-event ()
+ "Enable sending focus events."
+ (1value (setf (eat--t-term-focus-event-mode eat--t-term) t))
+ (funcall (eat--t-term-set-focus-ev-mode-fn eat--t-term) eat--t-term
+ t))
+
+(defun eat--t-disable-focus-event ()
+ "Disable sending focus events."
+ (1value (setf (eat--t-term-focus-event-mode eat--t-term) nil))
+ (funcall (eat--t-term-set-focus-ev-mode-fn eat--t-term) eat--t-term
+ nil))
+
+(defun eat--t-set-title (title)
+ "Set the title of terminal to TITLE."
+ ;; Update title.
+ (setf (eat--t-term-title eat--t-term) title)
+ ;; Inform the UI.
+ (funcall (eat--t-term-set-title-fn eat--t-term) eat--t-term title))
+
+(defun eat--t-set-cwd (url)
+ "Set the working directory of terminal to URL."
+ (setq url (url-generic-parse-url url))
+ (when (string= (url-type url) "file")
+ (let ((host (url-host url))
+ (dir (expand-file-name
+ (file-name-as-directory
+ (url-unhex-string (url-filename url))))))
+ ;; Inform the UI.
+ (funcall (eat--t-term-set-cwd-fn eat--t-term)
+ eat--t-term host dir))))
+
+(defun eat--t-send-device-attrs (n format)
+ "Return device attributes.
+
+FORMAT is the format of parameters in output. N should be zero."
+ (pcase-exhaustive format
+ ('nil
+ (when (= (or n 0) 0)
+ (funcall (eat--t-term-input-fn eat--t-term) eat--t-term
+ "\e[?12;4c")))
+ (?>
+ (when (= (or n 0) 0)
+ (funcall (eat--t-term-input-fn eat--t-term) eat--t-term
+ "\e[>0;0;0c")))))
+
+(defun eat--t-send-graphics-attrs (attr operation)
+ "Send graphics attributes.
+
+ATTR is the attribute requested, OPERATION is the thing to do (only
+reading an attribute is supported)."
+ (funcall
+ (eat--t-term-input-fn eat--t-term) eat--t-term
+ (if (memq operation '(1 4))
+ (pcase attr
+ (1
+ ;; TODO: Maybe provide an user option to control the value?
+ ;; count?
+ (format "\e[?1;0;256S"))
+ (2
+ ;; TODO: Maybe provide an user option to control the value?
+ (let ((disp (eat--t-term-display eat--t-term)))
+ (format "\e[?2;0;%i;%iS"
+ (min (* (eat--t-disp-width disp)
+ (eat--t-term-char-width eat--t-term))
+ 1000)
+ (min (* (eat--t-disp-height disp)
+ (eat--t-term-char-height eat--t-term))
+ 1000))))
+ (_
+ (format "\e[?%i;1S" attr)))
+ (format "\e[?%i;%iS" attr
+ (if (<= 1 attr 2) (if (<= 2 operation 3) 3 2) 1)))))
+
+(defun eat--t-report-foreground-color ()
+ "Report the current default foreground color to the client."
+ (funcall
+ (eat--t-term-input-fn eat--t-term) eat--t-term
+ (let ((rgb (or (color-values (face-foreground 'default))
+ ;; On terminals like TTYs the above returns nil.
+ ;; Terminals usually have a white foreground, so...
+ '(255 255 255))))
+ (format "\e]10;rgb:%04x/%04x/%04x\e\\"
+ (pop rgb) (pop rgb) (pop rgb)))))
+
+(defun eat--t-report-background-color ()
+ "Report the current default background color to the client."
+ (funcall
+ (eat--t-term-input-fn eat--t-term) eat--t-term
+ (let ((rgb (or (color-values (face-background 'default))
+ ;; On terminals like TTYs the above returns nil.
+ ;; Terminals usually have a black background, so...
+ '(0 0 0))))
+ (format "\e]11;rgb:%04x/%04x/%04x\e\\"
+ (pop rgb) (pop rgb) (pop rgb)))))
+
+(defun eat--t-manipulate-selection (targets data)
+ "Set and send current selection.
+
+TARGETS is a string containing zero or more characters from the set
+`c', `p', `q', `s', `0', `1', `2', `3', `4', `5', `6', and `7'. DATA
+is the selection data encoded in base64."
+ (when (string-empty-p targets)
+ (setq targets "s0"))
+ (if (string= data "?")
+ ;; The client is requesting for clipboard content, let's try to
+ ;; fulfill the request.
+ (funcall
+ (eat--t-term-input-fn eat--t-term) eat--t-term
+ (let ((str nil)
+ (n 0))
+ ;; Remove invalid and duplicate targets from TARGETS before
+ ;; processing it and sending it back.
+ (setq targets
+ (apply #'string
+ (cl-delete-duplicates
+ (cl-delete-if-not
+ (lambda (c) (or (<= ?0 c ?7)
+ (memq c '(?c ?p ?q ?s))))
+ (string-to-list targets)))))
+ (while (and (not str) (< n (length targets)))
+ (setq
+ str
+ (pcase (aref targets n)
+ ;; c, p, q and s targets are handled by the UI, and they
+ ;; might refuse to give the clipboard content.
+ (?c
+ (funcall
+ (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :clipboard t))
+ (?p
+ (funcall
+ (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :primary t))
+ (?q
+ (funcall
+ (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :secondary t))
+ (?s
+ (funcall
+ (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :select t))
+ ;; 0 to 9 targets are handled by us, and always work.
+ ((and (pred (<= ?0))
+ (pred (>= ?7))
+ i)
+ (aref (eat--t-term-cut-buffers eat--t-term)
+ (- i ?0)))))
+ (cl-incf n))
+ ;; No string to send, so send an empty string.
+ (unless str (setq str ""))
+ (format "\e]52;%s;%s\e\\" targets
+ (base64-encode-string (encode-coding-string
+ str locale-coding-system)
+ 'no-line-break))))
+ ;; The client is requesting to set clipboard content, let's try to
+ ;; fulfill the request.
+ (let ((str (ignore-errors
+ (decode-coding-string (base64-decode-string data)
+ locale-coding-system))))
+ (seq-doseq (target targets)
+ (pcase target
+ ;; c, p, q and s targets are handled by the UI, and they
+ ;; might reject the new clipboard content.
+ (?c
+ (funcall (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :clipboard str))
+ (?p
+ (funcall (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :primary str))
+ (?q
+ (funcall (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :secondary str))
+ (?s
+ (funcall (eat--t-term-manipulate-selection-fn eat--t-term)
+ eat--t-term :select str))
+ ;; 0 to 7 targets are handled by us, and always work.
+ ((and (pred (<= ?0))
+ (pred (>= ?7))
+ i)
+ (aset (eat--t-term-cut-buffers eat--t-term) (- i ?0)
+ str)))))))
+
+(defun eat--t-sixel-init ()
+ "Initialize Sixel mode."
+ (let ((default-palette
+ (eval-when-compile
+ (vconcat '("#000000" "#3333cc" "#cc2121" "#33cc33"
+ "#cc33cc" "#33cccc" "#cccc33" "#878787"
+ "#424242" "#545499" "#994242" "#549954"
+ "#995499" "#549999" "#999954" "#cccccc")
+ (make-list 240 "#000000")))))
+ (dotimes (i 256)
+ (setf (aref (eat--t-term-sixel-palette eat--t-term) i)
+ (aref default-palette i))))
+ ;; We just follow XTerm and set the initial foreground color to 3.
+ ;; But even the XTerm authors are unsure about what was the actual
+ ;; default.
+ (setf (eat--t-term-sixel-color eat--t-term) 3)
+ (while (< (eat--t-term-sixel-buffer-size eat--t-term)
+ (+ (* (eat--t-term-char-height eat--t-term) 2) 5))
+ (let ((new
+ (cons (cons 0 (make-vector 1000 nil))
+ (cons (cadr (eat--t-term-sixel-buffer eat--t-term))
+ (eat--t-term-sixel-buffer eat--t-term)))))
+ (setf (cddr (cadr (eat--t-term-sixel-buffer eat--t-term))) new)
+ (setf (cadr (eat--t-term-sixel-buffer eat--t-term)) new)
+ (setf (eat--t-term-sixel-buffer eat--t-term) new))
+ (cl-incf (eat--t-term-sixel-buffer-size eat--t-term)))
+ (let* ((beg (eat--t-term-sixel-buffer eat--t-term))
+ (line beg)
+ (loop t))
+ (while loop
+ (cl-loop for i from 0 to (1- (caar line))
+ do (aset (cdar line) i nil))
+ (setf (caar line) 0)
+ (setq line (cddr line))
+ (when (eq line beg)
+ (setq loop nil))))
+ (let ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (setf (eat--t-cur-sixel-x cursor) 0)
+ (setf (eat--t-cur-sixel-y cursor) 0)
+ (setf (eat--t-cur-sixel-beg cursor)
+ (eat--t-term-sixel-buffer eat--t-term))
+ (unless (eat--t-term-sixel-scroll-mode eat--t-term)
+ (setf (eat--t-term-sixel-initial-cursor-pos eat--t-term)
+ (cons (eat--t-cur-y cursor) (eat--t-cur-x cursor)))
+ (eat--t-goto 1 1))))
+
+(defun eat--t-sixel-write (str beg end count)
+ "Write substring [BEG..END) of STR COUNT times to Sixel buffer."
+ (let ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (dotimes (_ count)
+ (cl-loop
+ for i from beg to (1- end) do
+ (when (= (eat--t-cur-sixel-x cursor) 1000)
+ (setf (eat--t-cur-sixel-x cursor) 999))
+ (let ((bitmap (- (aref str i) ??))
+ (j 0)
+ (line (eat--t-cur-sixel-beg cursor))
+ (color (aref (eat--t-term-sixel-palette eat--t-term)
+ (eat--t-term-sixel-color eat--t-term))))
+ (while (< j 6)
+ (when (/= (logand bitmap (ash 1 j)) 0)
+ (aset (cdar line) (eat--t-cur-sixel-x cursor) color))
+ (setf line (cddr line))
+ (cl-incf j)))
+ (cl-incf (eat--t-cur-sixel-x cursor))))
+ (let ((i 5)
+ (line (eat--t-cur-sixel-beg cursor)))
+ (while (>= i 0)
+ (setf (caar line) (max (eat--t-cur-sixel-x cursor)
+ (caar line)))
+ (setf line (cddr line))
+ (cl-decf i)))
+ (when (= (eat--t-cur-sixel-x cursor) 1000)
+ (setf (eat--t-cur-sixel-x cursor) 999))))
+
+(defun eat--t-sixel-render-bitmap (bitmap)
+ "Render BITMAP.
+
+CHAR-SIZE is the width and height of a character."
+ (let ((char-size (cons (length (aref bitmap 0)) (length bitmap))))
+ (pcase-exhaustive (eat--t-term-sixel-render-format eat--t-term)
+ ('none)
+ ('background
+ (when-let* ((color (aref (aref bitmap 0) 0)))
+ (put-text-property (point) (1+ (point)) 'face
+ `(:background ,color))))
+ ('half-block
+ (let ((fg (aref (aref bitmap (/ (cdr char-size) 2)) 0))
+ (bg (aref (aref bitmap 0) 0)))
+ (when (or fg bg)
+ (put-text-property
+ (point) (1+ (point)) 'display
+ (propertize
+ "▄" 'face
+ `(,@(and bg `(:background ,bg))
+ :foreground ,(or fg (face-background 'default))))))))
+ ('svg
+ (put-text-property
+ (point) (1+ (point)) 'display
+ `(image
+ :type svg
+ :data ,(apply
+ #'concat
+ (format "<svg width=\"%i\" height=\"%i\""
+ (car char-size) (cdr char-size))
+ " version=\"1.1\""
+ " xmlns=\"http://www.w3.org/2000/svg\""
+ " xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
+ (let ((strs '("</svg>")))
+ (dotimes (i (cdr char-size))
+ (dotimes (j (car char-size))
+ (when-let* ((color (aref (aref bitmap i) j)))
+ (push
+ (concat
+ "<rect width=\"1\" height=\"1\""
+ (format " x=\"%i\" y=\"%i\"" j i)
+ (format " fill=\"%s\"></rect>" color))
+ strs))))
+ strs))
+ ,@(eat--t-term-sixel-image-extra-props eat--t-term))))
+ ('xpm
+ (put-text-property
+ (point) (1+ (point)) 'display
+ `(image
+ :type xpm
+ :data ,(let ((color-map nil)
+ (pixmap nil)
+ (color-key-length
+ (length (format "%x" (* (car char-size)
+ (cdr char-size))))))
+ (dotimes (i (cdr char-size))
+ (push nil pixmap)
+ (dotimes (j (car char-size))
+ (let ((idx (format
+ (format "%%0%ix" color-key-length)
+ (+ (* i (car char-size)) j)))
+ (color (or (aref (aref bitmap i) j)
+ "None")))
+ (push (format "%s c %s" idx color) color-map)
+ (push idx (car pixmap)))))
+ (concat
+ "/* XPM */\n"
+ "static char * XFACE[] = {\n"
+ (format "\"%i %i %i %i\",\n" (car char-size)
+ (cdr char-size) (* (car char-size)
+ (cdr char-size))
+ color-key-length)
+ (mapconcat (lambda (line)
+ (format "\"%s\",\n" line))
+ color-map "")
+ (mapconcat (lambda (row)
+ (format "\"%s\"" (string-join
+ (nreverse row))))
+ (nreverse pixmap) ",\n")
+ "\n};"))
+ ,@(eat--t-term-sixel-image-extra-props eat--t-term)))))))
+
+(defun eat--t-sixel-flush-line (nullify)
+ "Flush current (not Sixel) line to the display.
+
+If NULLIFY is non-nil, nullify flushed part of Sixel buffer."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (sixel-col-count 0)
+ (char-count 0)
+ (lines [])
+ (char-size (cons (eat--t-term-char-width eat--t-term)
+ (eat--t-term-char-height eat--t-term))))
+ (when (< (length lines) (cdr char-size))
+ (setq lines (make-vector (cdr char-size) nil)))
+ (let ((line (eat--t-term-sixel-buffer eat--t-term)))
+ (dotimes (i (cdr char-size))
+ (setq sixel-col-count (max sixel-col-count (caar line)))
+ (aset lines i (car line))
+ (setf line (cddr line))))
+ (setq char-count
+ (min
+ (/ (+ sixel-col-count (1- (car char-size)))
+ (car char-size))
+ (- (eat--t-disp-width disp) (1- (eat--t-cur-x cursor)))))
+ (save-excursion
+ (let ((j 0))
+ (dotimes (_ char-count)
+ (unless (equal (get-text-property
+ (point) 'eat--t-sixel-bitmap-size)
+ char-size)
+ (let ((color
+ (unless (memq (char-after (point)) '(?\n nil))
+ (plist-get (get-text-property (point) 'face)
+ :background)))
+ (bitmap (make-vector (cdr char-size) nil)))
+ (dotimes (i (cdr char-size))
+ (aset bitmap i (make-vector (car char-size) color)))
+ (insert
+ (propertize " " 'eat--t-sixel-bitmap-size char-size
+ 'eat--t-sixel-bitmap bitmap))
+ (unless (memq (char-after (point)) '(?\n nil))
+ (delete-region (point) (1+ (point))))
+ (backward-char)))
+ (let ((bitmap (get-text-property
+ (point) 'eat--t-sixel-bitmap))
+ (i 0))
+ (while (and (< i (car char-size))
+ (< j 1000))
+ (dotimes (k (cdr char-size))
+ (when-let* ((color (aref (cdr (aref lines k)) j)))
+ (setf (aref (aref bitmap k) i) color)))
+ (cl-incf i)
+ (cl-incf j))
+ (eat--t-sixel-render-bitmap bitmap))
+ (forward-char)
+ (eat--t-fix-partial-multi-col-char 'preserve-face))))
+ (dotimes (_ (cdr char-size))
+ (let ((line (eat--t-term-sixel-buffer eat--t-term)))
+ (when nullify
+ (cl-loop for i from 0 to (1- (caar line))
+ do (aset (cdar line) i nil))
+ (setf (caar line) 0))
+ (setf (eat--t-term-sixel-buffer eat--t-term) (cddr line))))
+ (cl-decf (eat--t-cur-sixel-y cursor) (cdr char-size))))
+
+(defun eat--t-sixel-newline ()
+ "Move to a new Sixel line."
+ (let ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (setf (eat--t-cur-sixel-x cursor) 0)
+ (cl-incf (eat--t-cur-sixel-y cursor) 6)
+ (dotimes (_ 6)
+ (setf (eat--t-cur-sixel-beg cursor)
+ (cddr (eat--t-cur-sixel-beg cursor))))
+ (while (>= (eat--t-cur-sixel-y cursor)
+ (eat--t-term-char-height eat--t-term))
+ (eat--t-sixel-flush-line 'nullify)
+ (if (eat--t-term-sixel-scroll-mode eat--t-term)
+ (eat--t-index)
+ (eat--t-cur-down)))))
+
+(defun eat--t-sixel-set-color-reg (reg spec)
+ "Set Sixel color register REG as described by SPEC."
+ (when (<= reg 255)
+ (let ((color
+ (cond
+ ((= (car spec) 1)
+ (when (and (<= (nth 1 spec) 360)
+ (<= (nth 2 spec) 100)
+ (<= (nth 3 spec) 100))
+ (let ((rgb (color-hsl-to-rgb (/ (nth 1 spec) 360.0)
+ (/ (nth 3 spec) 100.0)
+ (/ (nth 2 spec) 100.0))))
+ (color-rgb-to-hex (nth 0 rgb) (nth 1 rgb)
+ (nth 2 rgb) 2))))
+ ((= (car spec) 2)
+ (when (and (<= (nth 1 spec) 100)
+ (<= (nth 2 spec) 100)
+ (<= (nth 3 spec) 100))
+ (color-rgb-to-hex (/ (nth 1 spec) 100.0)
+ (/ (nth 2 spec) 100.0)
+ (/ (nth 3 spec) 100.0) 2))))))
+ (when color
+ (aset (eat--t-term-sixel-palette eat--t-term) reg color)))))
+
+(defun eat--t-sixel-cleanup ()
+ "Cleanup before potential exit from Sixel mode."
+ (cl-letf* ((cursor (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term)))
+ ((eat--t-cur-sixel-y cursor) (eat--t-cur-sixel-y cursor))
+ ((eat--t-term-sixel-buffer eat--t-term)
+ (eat--t-term-sixel-buffer eat--t-term)))
+ (while (>= (eat--t-cur-sixel-y cursor) -5)
+ (eat--t-sixel-flush-line nil)
+ (if (eat--t-term-sixel-scroll-mode eat--t-term)
+ (eat--t-index)
+ (eat--t-cur-down))))
+ (unless (eat--t-term-sixel-scroll-mode eat--t-term)
+ (eat--t-goto
+ (car (eat--t-term-sixel-initial-cursor-pos eat--t-term))
+ (cdr (eat--t-term-sixel-initial-cursor-pos eat--t-term)))))
+
+(defun eat--t-sixel-enable-scrolling ()
+ "Enable Sixel scrolling mode."
+ (setf (eat--t-term-sixel-scroll-mode eat--t-term) t))
+
+(defun eat--t-sixel-disable-scrolling ()
+ "Disable Sixel scrolling mode."
+ (setf (eat--t-term-sixel-scroll-mode eat--t-term) nil))
+
+(defun eat--t-ui-cmd (cmd)
+ "Call UI's UIC handler to handle CMD."
+ (funcall (eat--t-term-ui-cmd-fn eat--t-term) eat--t-term cmd))
+
+(defun eat--t-set-modes (params format)
+ "Set modes according to PARAMS in format FORMAT."
+ ;; Dispatch the request to appropriate function.
+ (pcase format
+ ('nil
+ (while params
+ (pcase (pop params)
+ ('(4)
+ (eat--t-insert-mode)))))
+ (??
+ (while params
+ (pcase (pop params)
+ ('(1)
+ (eat--t-enable-keypad))
+ ('(7)
+ (eat--t-enable-auto-margin))
+ ('(9)
+ (eat--t-enable-x10-mouse))
+ ('(12)
+ (eat--t-blinking-cursor))
+ ('(25)
+ (eat--t-show-cursor))
+ ('(80)
+ (eat--t-sixel-disable-scrolling))
+ ('(1000)
+ (eat--t-enable-normal-mouse))
+ ('(1002)
+ (eat--t-enable-button-event-mouse))
+ ('(1003)
+ (eat--t-enable-any-event-mouse))
+ ('(1004)
+ (eat--t-enable-focus-event))
+ ('(1006)
+ (eat--t-enable-sgr-mouse-encoding))
+ ('(1048)
+ (eat--t-save-cur))
+ (`(,(or 1047 1049))
+ (eat--t-enable-alt-disp))
+ ('(2004)
+ (eat--t-enable-bracketed-yank)))))))
+
+(defun eat--t-reset-modes (params format)
+ "Reset modes according to PARAMS in format FORMAT."
+ ;; Dispatch the request to appropriate function.
+ (pcase format
+ ('nil
+ (while params
+ (pcase (pop params)
+ ('(4)
+ (eat--t-replace-mode)))))
+ (??
+ (while params
+ (pcase (pop params)
+ ('(1)
+ (eat--t-disable-keypad))
+ ('(7)
+ (eat--t-disable-auto-margin))
+ ('(12)
+ (eat--t-non-blinking-cursor))
+ ('(25)
+ (eat--t-hide-cursor))
+ ('(80)
+ (eat--t-sixel-enable-scrolling))
+ (`(,(or 9 1000 1002 1003))
+ (eat--t-disable-mouse))
+ ('(1004)
+ (eat--t-disable-focus-event))
+ ('(1006)
+ (eat--t-disable-sgr-mouse-encoding))
+ ('(1047)
+ (eat--t-disable-alt-disp 'dont-move-cursor))
+ ('(1048)
+ (eat--t-restore-cur))
+ ('(1049)
+ (eat--t-disable-alt-disp))
+ ('(2004)
+ (eat--t-disable-bracketed-yank)))))))
+
+(defun eat--t-handle-output (output)
+ "Parse and evaluate OUTPUT."
+ (let ((index 0))
+ (while (/= index (length output))
+ (pcase-exhaustive (eat--t-term-parser-state eat--t-term)
+ ('nil
+ (let ((ins-beg index))
+ (while (and (/= index (length output))
+ (not (memq (aref output index)
+ '( ?\0 ?\a ?\b ?\t ?\n ?\v ?\f ?\r
+ ?\C-n ?\C-o ?\e #x7f))))
+ (cl-incf index))
+ (when (/= ins-beg index)
+ ;; Insert.
+ (eat--t-write output ins-beg index))
+ (when (/= index (length output))
+ ;; Dispatch control sequence.
+ (cl-incf index)
+ (pcase (aref output (1- index))
+ (?\a
+ (eat--t-bell))
+ (?\b
+ (eat--t-cur-left 1))
+ (?\t
+ (eat--t-horizontal-tab 1))
+ (?\n
+ (eat--t-line-feed))
+ (?\v
+ (eat--t-index))
+ (?\f
+ (eat--t-form-feed))
+ (?\r
+ ;; Avoid going to line home just before a line feed,
+ ;; we can just insert a new line if we are at the
+ ;; end of display.
+ (unless (and (/= index (length output))
+ (= (aref output index) ?\n))
+ (eat--t-carriage-return)))
+ (?\C-n
+ (eat--t-change-charset 'g1))
+ (?\C-o
+ (eat--t-change-charset 'g0))
+ (?\e
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ '(read-esc))))
+ ;; Others are ignored.
+ ))))
+ ('(read-esc)
+ (let ((type (aref output index)))
+ (cl-incf index)
+ (1value (setf (eat--t-term-parser-state eat--t-term) nil))
+ ;; Dispatch control sequence.
+ (pcase type
+ ;; ESC (.
+ (?\(
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-standard g0 "")))
+ ;; ESC ).
+ (?\)
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-standard g1 "")))
+ ;; ESC *.
+ (?*
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-standard g2 "")))
+ ;; ESC +.
+ (?+
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-standard g3 "")))
+ ;; ESC -.
+ (?-
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-vt300 g1 "")))
+ ;; ESC ..
+ (?.
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-vt300 g2 "")))
+ ;; ESC /.
+ (?/
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-charset-vt300 g3 "")))
+ ;; ESC 7.
+ (?7
+ (eat--t-save-cur))
+ ;; ESC 8.
+ (?8
+ (eat--t-restore-cur))
+ ;; ESC D.
+ (?D
+ (eat--t-index))
+ ;; ESC E.
+ (?E
+ (eat--t-line-feed))
+ ;; ESC M.
+ (?M
+ (eat--t-reverse-index))
+ ;; ESC P, or DCS.
+ (?P
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ `(read-dcs-params (read-dcs-function)
+ ,(list nil)))))
+ ;; ESC X, or SOS.
+ (?X
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ '(read-sos ""))))
+ ;; ESC [, or CSI.
+ (?\[
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ '(read-csi-format))))
+ ;; ESC ], or OSC.
+ (?\]
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ '(read-osc ""))))
+ ;; ESC ^, or PM.
+ (?^
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ '(read-pm ""))))
+ ;; ESC _, or APC.
+ (?_
+ (1value (setf (eat--t-term-parser-state eat--t-term)
+ '(read-apc ""))))
+ ;; ESC c.
+ (?c
+ (eat--t-reset))
+ ;; ESC n.
+ (?n
+ (eat--t-change-charset 'g2))
+ ;; ESC o.
+ (?o
+ (eat--t-change-charset 'g3)))))
+ ('(read-csi-format)
+ (let ((format nil))
+ (pcase (aref output index)
+ (??
+ (setq format ??)
+ (cl-incf index))
+ (?>
+ (setq format ?>)
+ (cl-incf index))
+ (?=
+ (setq format ?=)
+ (cl-incf index)))
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-csi-params ,format ,(list (list nil))))))
+ (`(read-csi-params ,format ,params)
+ ;; Interpretion of the parameter depends on `format' and
+ ;; other things (including things we haven't gotten yet)
+ ;; according to the standard. We don't recognize any other
+ ;; format of parameters, so we can skip any checks.
+ (let ((loop t))
+ (while loop
+ (cond
+ ((= index (length output))
+ ;; Output exhausted. We need to wait for more.
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-csi-params ,format ,params))
+ (setq loop nil))
+ ((not (<= ?0 (aref output index) ?\;))
+ ;; End of parameters.
+ ;; NOTE: All parameter and their parts are in reverse
+ ;; order!
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-csi-function ,format ,params nil))
+ (setq loop nil))
+ (t
+ (cond
+ ((= (aref output index) ?:)
+ ;; New parameter substring.
+ (push nil (car params)))
+ ((= (aref output index) ?\;)
+ ;; New parameter.
+ (push (list nil) params))
+ (t ; (<= ?0 (aref output index) ?9)
+ ;; Number, save it.
+ (setf (caar params)
+ (+ (* (or (caar params) 0) 10)
+ (- (aref output index) #x30)))))
+ (cl-incf index))))))
+ (`(read-csi-function ,format ,params ,function)
+ (let ((loop t))
+ (while loop
+ (cond
+ ((= index (length output))
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-csi-function ,format ,params ,function))
+ (setq loop nil)))
+ (push (aref output index) function)
+ (cl-incf index)
+ (when (<= ?@ (car function) ?~)
+ ;; Now we have enough information to execute it!
+ (setq loop nil)
+ (setf (eat--t-term-parser-state eat--t-term) nil)
+ ;; NOTE: `function' and `params' are in reverse order!
+ (pcase (list function format params)
+ ;; CSI <n> @.
+ (`((?@) nil ((,n)))
+ (eat--t-insert-char n))
+ ;; CSI <n> A.
+ ;; CSI <n> k.
+ (`((,(or ?A ?k)) nil ((,n)))
+ (eat--t-cur-up n))
+ ;; CSI <n> B.
+ ;; CSI <n> e.
+ (`((,(or ?B ?e)) nil ((,n)))
+ (eat--t-cur-down n))
+ ;; CSI <n> C.
+ ;; CSI <n> a.
+ (`((,(or ?C ?a)) nil ((,n)))
+ (eat--t-cur-right n))
+ ;; CSI <n> D.
+ ;; CSI <n> j.
+ (`((,(or ?D ?j)) nil ((,n)))
+ (eat--t-cur-left n))
+ ;; CSI <n> E.
+ (`((?E) nil ((,n)))
+ (eat--t-beg-of-prev-line n))
+ ;; CSI <n> F.
+ (`((?F) nil ((,n)))
+ (eat--t-beg-of-next-line n))
+ ;; CSI <n> G.
+ ;; CSI <n> `.
+ (`((,(or ?G ?`)) nil ((,n)))
+ (eat--t-cur-horizontal-abs n))
+ ;; CSI <n> ; <m> H
+ ;; CSI <n> ; <m> f
+ (`((,(or ?H ?f)) nil ,(and (pred listp) params))
+ (eat--t-goto (caadr params) (caar params)))
+ ;; CSI <n> I.
+ (`((?I) nil ((,n)))
+ (eat--t-horizontal-tab n))
+ ;; CSI <n> J.
+ (`((?J) nil ((,n)))
+ (eat--t-erase-in-disp n))
+ ;; CSI <n> K.
+ (`((?K) nil ((,n)))
+ (eat--t-erase-in-line n))
+ ;; CSI <n> L.
+ (`((?L) nil ((,n)))
+ (eat--t-insert-line n))
+ ;; CSI <n> M.
+ (`((?M) nil ((,n)))
+ (eat--t-delete-line n))
+ ;; CSI <n> P.
+ (`((?P) nil ((,n)))
+ (eat--t-delete-char n))
+ ;; CSI <n> S.
+ (`((?S) nil ((,n)))
+ (eat--t-scroll-up n))
+ ;; CSI ? <n> ; <m> ; ... S.
+ (`((?S) ?? ,(or `((,_) (,operation) (,attr))
+ `((,_) (,_) (,operation) (,attr))))
+ (eat--t-send-graphics-attrs attr operation))
+ ;; CSI <n> T.
+ (`((?T) nil ((,n)))
+ (eat--t-scroll-down n))
+ ;; CSI <n> X.
+ (`((?X) nil ((,n)))
+ (eat--t-erase-char n))
+ ;; CSI <n> Z.
+ (`((?Z) nil ((,n)))
+ (eat--t-horizontal-backtab n))
+ ;; CSI <n> b.
+ (`((?b) nil ((,n)))
+ (eat--t-repeat-last-char n))
+ ;; CSI <n> c.
+ ;; CSI > <n> c.
+ (`((?c) ,format ((,n)))
+ (eat--t-send-device-attrs n format))
+ ;; CSI <n> d.
+ (`((?d) nil ((,n)))
+ (eat--t-cur-vertical-abs n))
+ ;; CSI ... h.
+ ;; CSI ? ... h.
+ (`((?h) ,format ,(and (pred listp) params))
+ ;; Reverse `params' to get it into the correct
+ ;; order.
+ (setq params (nreverse params))
+ (let ((p params))
+ (while p
+ (setf (car p) (nreverse (car p)))
+ (setq p (cdr p))))
+ (eat--t-set-modes params format))
+ ;; CSI ... l.
+ ;; CSI ? ... l.
+ (`((?l) ,format ,(and (pred listp) params))
+ ;; Reverse `params' to get it into the correct
+ ;; order.
+ (setq params (nreverse params))
+ (let ((p params))
+ (while p
+ (setf (car p) (nreverse (car p)))
+ (setq p (cdr p))))
+ (eat--t-reset-modes params format))
+ ;; CSI ... m.
+ (`((?m) nil ,(and (pred listp) params))
+ ;; Reverse `params' to get it into the correct
+ ;; order.
+ (setq params (nreverse params))
+ (let ((p params))
+ (while p
+ (setf (car p) (nreverse (car p)))
+ (setq p (cdr p))))
+ (eat--t-set-sgr-params params))
+ ;; CSI 6 n.
+ (`((?n) nil ((,n)))
+ (eat--t-device-status-report n))
+ ;; CSI <n> SP q.
+ (`((?q ?\ ) nil ((,n)))
+ (eat--t-set-cursor-style n))
+ ;; CSI <n> ; <n> r.
+ (`((?r) nil ,(and (pred listp) params))
+ (eat--t-change-scroll-region (caadr params)
+ (caar params)))
+ ;; CSI s.
+ (`((?s) nil nil)
+ (eat--t-save-cur))
+ ;; CSI u.
+ (`((?u) nil nil)
+ (eat--t-restore-cur)))))))
+ (`(,(and (or 'read-sos 'read-osc 'read-pm 'read-apc) state)
+ ,buf)
+ ;; Find the end of string.
+ (let ((match (string-match (if (eq state 'read-osc)
+ (rx (or ?\a ?\\))
+ (rx ?\\))
+ output index)))
+ (if (not match)
+ (progn
+ ;; Not found, store the text to process it later when
+ ;; we get the end of string.
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(,state ,(concat buf (substring output
+ index))))
+ (setq index (length output)))
+ ;; Matched! Get the string from the output and previous
+ ;; runs.
+ (let ((str (concat buf (substring output index
+ match))))
+ (setq index (match-end 0))
+ ;; Is it really the end of string?
+ (if (and (= (aref output match) ?\\)
+ (not (or (zerop (length str))
+ (= (aref str (1- (length str)))
+ ?\e))))
+ ;; No. Push the '\' character to process later.
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(,state ,(concat str "\\")))
+ ;; Yes! It's the end! We can parse it.
+ (when (= (aref output match) ?\\)
+ (setq str (substring str 0 (1- (length str)))))
+ (setf (eat--t-term-parser-state eat--t-term) nil)
+ ;; Dispatch control sequence.
+ (pcase state
+ ('read-osc
+ (pcase str
+ ;; OSC 0 ; <t> ST.
+ ;; OSC 2 ; <t> ST.
+ ((rx string-start (or ?0 ?2) ?\;
+ (let title (zero-or-more anything))
+ string-end)
+ (eat--t-set-title title))
+ ;; OSC 7 ; <t> ST.
+ ((rx string-start ?7 ?\;
+ (let url (zero-or-more anything))
+ string-end)
+ (eat--t-set-cwd url))
+ ;; OSC 1 0 ; ? ST.
+ ("10;?"
+ (eat--t-report-foreground-color))
+ ;; OSC 1 1 ; ? ST.
+ ("11;?"
+ (eat--t-report-background-color))
+ ;; OSC 5 1 ; <s> ST.
+ ((rx string-start "51;"
+ (let cmd (zero-or-more anything))
+ string-end)
+ (eat--t-ui-cmd cmd))
+ ;; OSC 5 2 ; <t> ; <s> ST.
+ ((rx string-start "52;"
+ (let targets
+ (zero-or-more (not (any ?\;))))
+ ?\; (let data (zero-or-more anything))
+ string-end)
+ (eat--t-manipulate-selection
+ targets data))))))))))
+ (`(read-dcs-params ,next-state ,params)
+ ;; There is no standard format of device control strings, but
+ ;; all DEC and XTerm DCS sequences (including those we
+ ;; support) follow this particular format.
+ (let ((loop t))
+ (while loop
+ (cond
+ ((= index (length output))
+ ;; Output exhausted. We need to wait for more.
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-dcs-params ,next-state ,params))
+ (setq loop nil))
+ ((not (or (<= ?0 (aref output index) ?9)
+ (= (aref output index) ?\;)))
+ ;; End of parameters.
+ ;; NOTE: All parameter and their parts are in reverse
+ ;; order!
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(,@next-state ,params))
+ (setq loop nil))
+ (t
+ (if (= (aref output index) ?\;)
+ ;; New parameter.
+ (push nil params)
+ ;; Number, save it.
+ (setf (car params)
+ (+ (* (or (car params) 0) 10)
+ (- (aref output index) #x30))))
+ (cl-incf index))))))
+ (`(read-dcs-function ,params)
+ (cl-incf index)
+ (pcase (aref output (1- index))
+ (?q
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-sixel init ,params)))
+ (?\e
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-potential-st (read-dcs-fallback))))
+ (_
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-dcs-fallback))
+ (cl-decf index))))
+ (`(read-potential-st ,else)
+ (if (/= (aref output index) ?\\)
+ (setf (eat--t-term-parser-state eat--t-term) else)
+ (setf (eat--t-term-parser-state eat--t-term) nil)
+ (cl-incf index)))
+ (`(read-dcs-fallback)
+ (let ((loop t))
+ (while (and loop (/= index (length output)))
+ (when (= (aref output index) ?\e)
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-potential-st (read-dcs-fallback)))
+ (setq loop nil))
+ (cl-incf index))))
+ (`(read-sixel ,cmd ,params)
+ (when cmd
+ (pcase cmd
+ ('init
+ (eat--t-sixel-init))
+ ('set-color
+ (when (and (= (length params) 1)
+ (<= (or (car params) 0) 255))
+ (setf (eat--t-term-sixel-color eat--t-term)
+ (or (car params) 0)))
+ (when (= (length params) 5)
+ (cl-destructuring-bind (z y x coord-sys reg) params
+ (eat--t-sixel-set-color-reg
+ (or reg 0) (list coord-sys (or x 0) (or y 0)
+ (or z 0))))))
+ ('rle
+ (eat--t-sixel-write output index (1+ index)
+ (or (car params) 0))
+ (cl-incf index))
+ ('set-raster-attr
+ ;; TODO: Implement.
+ ))
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-sixel nil nil)))
+ (let ((loop t))
+ (while (and loop (/= index (length output)))
+ (if (<= ?? (aref output index) ?~)
+ (let ((ins-beg index))
+ (while (and (/= index (length output))
+ (<= ?? (aref output index) ?~))
+ (cl-incf index))
+ (eat--t-sixel-write output ins-beg index 1))
+ (cl-incf index)
+ (pcase (aref output (1- index))
+ (?!
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-dcs-params (read-sixel rle)
+ ,(list nil)))
+ (setq loop nil))
+ (?-
+ (eat--t-sixel-newline))
+ (?$
+ (setf (eat--t-cur-sixel-x
+ (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term)))
+ 0))
+ (?\#
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-dcs-params (read-sixel set-color)
+ ,(list nil)))
+ (setq loop nil))
+ (?\"
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-dcs-params (read-sixel set-raster-attr)
+ ,(list nil)))
+ (setq loop nil))
+ (?\e
+ (eat--t-sixel-cleanup)
+ (setf (eat--t-term-parser-state eat--t-term)
+ '(read-potential-st (read-dcs-fallback)))
+ (setq loop nil)))))))
+ (`(read-charset-standard ,slot ,buf)
+ ;; Find the end.
+ (let ((match (string-match (rx (any ?0 ?2 ?4 ?5 ?6 ?7 ?9 ?<
+ ?= ?> ?? ?A ?B ?C ?E ?H
+ ?K ?Q ?R ?Y ?Z ?f))
+ output index)))
+ (if (not match)
+ (progn
+ ;; Not found, store the text to process it later when
+ ;; we find the end.
+ (setf (eat--t-term-parser-state eat--t-term)
+ `(read-charset-standard
+ ,slot ,(concat buf (substring
+ output index))))
+ (setq index (length output)))
+ ;; Got the end!
+ (let ((str (concat buf (substring output index
+ (match-end 0)))))
+ (setq index (match-end 0))
+ (setf (eat--t-term-parser-state eat--t-term) nil)
+ ;; Set the character set.
+ (eat--t-set-charset
+ slot
+ (pcase str
+ ;; ESC ( 0.
+ ;; ESC ) 0.
+ ;; ESC * 0.
+ ;; ESC + 0.
+ ("0" 'dec-line-drawing)
+ ;; ESC ( B.
+ ;; ESC ) B.
+ ;; ESC * B.
+ ;; ESC + B.
+ ("B" 'us-ascii)))))))
+ (`(read-charset-vt300 ,_slot)
+ (cl-incf index)
+ (setf (eat--t-term-parser-state eat--t-term) nil)
+ ;; Nothing. This is here to just recognize the sequence.
+ )))))
+
+(defun eat--t-resize (width height)
+ "Resize terminal to WIDTH x HEIGHT."
+ (let* ((disp (eat--t-term-display eat--t-term))
+ (cursor (eat--t-disp-cursor disp))
+ (old-width (eat--t-disp-width disp))
+ (old-height (eat--t-disp-height disp)))
+ ;; Don't do anything if size hasn't changed, or the new size is
+ ;; too small.
+ (when (and (not (and (eq old-width width)
+ (eq old-height height)))
+ (>= width 1)
+ (>= height 1))
+ ;; Update state.
+ (setf (eat--t-disp-width disp) width)
+ (setf (eat--t-disp-height disp) height)
+ (setf (eat--t-term-scroll-begin eat--t-term) 1)
+ (setf (eat--t-term-scroll-end eat--t-term)
+ (eat--t-disp-height disp))
+ (set-marker (eat--t-cur-position cursor) (point))
+ (if (eat--t-term-main-display eat--t-term)
+ ;; For alternative display, just delete the part of the
+ ;; display that went out of the edges. So if the terminal
+ ;; was enlarged, we don't have anything to do.
+ (when (or (< width old-width)
+ (< height old-height))
+ ;; Go to the beginning of display.
+ (goto-char (eat--t-disp-begin disp))
+ (let ((l 0))
+ (while (and (< l height) (not (eobp)))
+ (eat--t-col-motion width)
+ (delete-region (point) (car (eat--t-eol)))
+ (unless (eobp)
+ (if (< (1+ l) height)
+ (forward-char)
+ (delete-region (point) (point-max))
+ (let ((y (eat--t-cur-y cursor))
+ (x (eat--t-cur-x cursor)))
+ (eat--t-goto 1 1)
+ (eat--t-goto y x))))
+ (cl-incf l))))
+ ;; REVIEW: This works, but it is very simple. Most
+ ;; terminals have more sophisticated mechanisms to do this.
+ ;; It would be nice thing have them here.
+ ;; Go to the beginning of display.
+ (goto-char (eat--t-disp-begin disp))
+ ;; Try to move to the end of previous line, maybe that's a
+ ;; part of a too long line.
+ (unless (bobp)
+ (backward-char))
+ ;; Join all long lines.
+ (while (not (eobp))
+ (eat--t-join-long-line))
+ ;; Go to display beginning again and break long lines.
+ (goto-char (eat--t-disp-begin disp))
+ (while (not (eobp))
+ (eat--t-break-long-line (eat--t-disp-width disp)))
+ ;; Calculate the beginning position of display.
+ (goto-char (point-max))
+ ;; TODO: This part needs explanation.
+ (let ((disp-begin (car (eat--t-bol (- (1- height))))))
+ (when (< (eat--t-disp-begin disp) disp-begin)
+ (goto-char (max (- (eat--t-disp-begin disp) 1)
+ (point-min)))
+ (set-marker (eat--t-disp-begin disp) disp-begin)
+ (while (< (point) (1- (eat--t-disp-begin disp)))
+ (eat--t-join-long-line
+ (1- (eat--t-disp-begin disp))))))
+ ;; Update the cursor if needed.
+ (when (< (eat--t-cur-position cursor)
+ (eat--t-disp-begin disp))
+ (set-marker (eat--t-cur-position cursor)
+ (eat--t-disp-begin disp)))
+ ;; Update the coordinates of cursor.
+ (goto-char (eat--t-cur-position cursor))
+ (setf (eat--t-cur-x cursor) (1+ (eat--t-current-col)))
+ (goto-char (eat--t-disp-begin disp))
+ (setf (eat--t-cur-y cursor)
+ (let ((y 0))
+ (while (< (point) (eat--t-cur-position cursor))
+ (condition-case nil
+ (search-forward
+ "\n" (eat--t-cur-position cursor))
+ (search-failed
+ (goto-char (eat--t-cur-position cursor))))
+ (cl-incf y))
+ (when (or (= (point) (point-min))
+ (= (char-before) ?\n))
+ (cl-incf y))
+ (max y 1)))))))
+
+;;;###autoload
+(defun eat-term-make (buffer position)
+ "Make a Eat terminal at POSITION in BUFFER."
+ (eat--t-make-term
+ :buffer buffer
+ :begin (copy-marker position t)
+ :end (copy-marker position)
+ :display (eat--t-make-disp
+ :begin (copy-marker position)
+ :old-begin (copy-marker position)
+ :cursor (eat--t-make-cur
+ :position (copy-marker position)))))
+
+(defun eat-term-p (object)
+ "Return non-nil if OBJECT is a Eat terminal."
+ (eat--t-term-p object))
+
+(defun eat-term-live-p (object)
+ "Return non-nil if OBJECT is a live Eat terminal."
+ (and (eat-term-p object)
+ (not (not (eat--t-term-buffer object)))))
+
+(defmacro eat--t-ensure-live-term (object)
+ "Signal error if OBJECT is not a live Eat terminal."
+ `(unless (eat-term-live-p ,object)
+ (error "%s is not a live Eat terminal"
+ ,(upcase (symbol-name object)))))
+
+(defmacro eat--t-with-env (terminal &rest body)
+ "Setup the environment for TERMINAL and eval BODY in it."
+ (declare (indent 1))
+ `(let ((eat--t-term ,terminal))
+ (eat--t-ensure-live-term ,terminal)
+ (with-current-buffer (eat--t-term-buffer eat--t-term)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (eat--t-term-begin eat--t-term)
+ (eat--t-term-end eat--t-term))
+ (goto-char (eat--t-cur-position
+ (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term))))
+ (unwind-protect
+ (progn ,@body)
+ (set-marker (eat--t-cur-position
+ (eat--t-disp-cursor
+ (eat--t-term-display eat--t-term)))
+ (point))
+ (set-marker (eat--t-term-begin eat--t-term) (point-min))
+ (set-marker (eat--t-term-end eat--t-term)
+ (point-max))))))))
+
+(defun eat-term-delete (terminal)
+ "Delete TERMINAL and do any cleanup to do."
+ (eat--t-ensure-live-term terminal)
+ (let ((inhibit-quit t)
+ (eat--t-term terminal))
+ (with-current-buffer (eat--t-term-buffer eat--t-term)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (eat--t-term-begin eat--t-term)
+ (eat--t-term-end eat--t-term))
+ (eat--t-set-cursor-state :default)
+ ;; Go to the beginning of display.
+ (goto-char (eat--t-disp-begin
+ (eat--t-term-display eat--t-term)))
+ ;; Join all long lines.
+ (unless (bobp)
+ (backward-char))
+ (while (not (eobp))
+ (eat--t-join-long-line)))))
+ (setf (eat--t-term-buffer eat--t-term) nil)))
+
+(defun eat-term-reset (terminal)
+ "Reset TERMINAL."
+ (let ((inhibit-quit t))
+ (eat--t-with-env terminal
+ (eat--t-reset))))
+
+(defun eat-term-parameter (terminal parameter)
+ "Return the value of parameter PARAMETER of TERMINAL."
+ (eat--t-ensure-live-term terminal)
+ (gethash parameter (eat--t-term-params terminal)))
+
+(defun eat-term-parameters (terminal)
+ "Return the parameter-alist of TERMINAL."
+ (eat--t-ensure-live-term terminal)
+ (let ((alist nil))
+ (maphash (lambda (key val) (push (cons key val) alist))
+ (eat--t-term-params terminal))))
+
+(defun eat-term-set-parameter (terminal parameter value)
+ "Set the value of parameter PARAMETER of TERMINAL to VALUE."
+ (eat--t-ensure-live-term terminal)
+ ;; Handle special parameters, and reject invalid values.
+ (pcase parameter
+ ('input-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-input-fn terminal) value))
+ ('ring-bell-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-bell-fn terminal) value))
+ ('set-cursor-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-set-cursor-fn terminal) value))
+ ('grab-mouse-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-grab-mouse-fn terminal) value))
+ ('grab-focus-events-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-set-focus-ev-mode-fn terminal) value))
+ ('manipulate-selection-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-manipulate-selection-fn terminal) value))
+ ('set-title-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-set-title-fn terminal) value))
+ ('set-cwd-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-set-cwd-fn terminal) value))
+ ('ui-command-function
+ (unless (functionp value)
+ (signal 'wrong-type-argument (list 'functionp value)))
+ (setf (eat--t-term-ui-cmd-fn terminal) value))
+ ('char-dimensions
+ (unless (and (consp value)
+ (integerp (car value))
+ (> (car value) 0)
+ (integerp (cdr value))
+ (> (cdr value) 0))
+ (signal 'wrong-type-argument (list 'consp value)))
+ (setf (eat--t-term-char-width terminal) (car value))
+ (setf (eat--t-term-char-height terminal) (cdr value)))
+ ('sixel-render-format
+ (unless (memq value '(background half-block svg xpm none))
+ (error "`sixel-render-format' parameter must be set to one of \
+the supported formats"))
+ (setf (eat--t-term-sixel-render-format terminal) value))
+ ('sixel-image-extra-properties
+ (setf (eat--t-term-sixel-image-extra-props terminal) value))
+ ('bold-face
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (eat--t-term-bold-face terminal) value))
+ ('faint-face
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (eat--t-term-faint-face terminal) value))
+ ('italic-face
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (eat--t-term-italic-face terminal) value))
+ ('slow-blink-face
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (eat--t-term-slow-blink-face terminal) value))
+ ('fast-blink-face
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (eat--t-term-fast-blink-face terminal) value))
+ ((and (pred symbolp)
+ (let (rx string-start "color-"
+ (let number (one-or-more (any (?0 . ?9))))
+ "-face" string-end)
+ (symbol-name parameter))
+ (let (and (pred (<= 0))
+ (pred (>= 255))
+ index)
+ (string-to-number number)))
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (aref (eat--t-term-color-faces terminal) index)
+ value))
+ ((and (pred symbolp)
+ (let (rx string-start "font-"
+ (let number (one-or-more (any (?0 . ?9))))
+ "-face" string-end)
+ (symbol-name parameter))
+ (let (and (pred (<= 0))
+ (pred (>= 255))
+ index)
+ (string-to-number number)))
+ (unless (and (symbolp value) (facep value))
+ (signal 'wrong-type-argument (list '(symbolp facep) value)))
+ (setf (aref (eat--t-term-font-faces terminal) index)
+ value)))
+ ;; Set the parameter.
+ (puthash parameter value (eat--t-term-params terminal)))
+
+(gv-define-setter eat-term-parameter (value terminal parameter)
+ `(eat-term-set-parameter ,terminal ,parameter ,value))
+
+(defun eat-term-cursor-type (terminal)
+ "Return the cursor state of TERMINAL.
+
+The return value can be one of the following:
+
+ `:invisible' Invisible cursor.
+ `:block' Block (filled box) cursor (default).
+ `:blinking-block' Blinking block cursor.
+ `:bar' Vertical bar cursor.
+ `:blinking-bar' Blinking vertical bar cursor.
+ `:underline' Horizontal bar cursor.
+ `:blinking-underline' Blinking horizontal bar cursor."
+ (eat--t-ensure-live-term terminal)
+ (if (eat--t-term-cur-visible-p terminal)
+ (eat--t-term-cur-state terminal)
+ :invisible))
+
+(defun eat-term-beginning (terminal)
+ "Return the beginning position of TERMINAL.
+
+Don't use markers to store the position, call this function whenever
+you need the position."
+ (eat--t-ensure-live-term terminal)
+ (eat--t-term-begin terminal))
+
+(defun eat-term-end (terminal)
+ "Return the end position of TERMINAL.
+
+This is also the end position of TERMINAL's display.
+
+Don't use markers to store the position, call this function whenever
+you need the position."
+ (eat--t-ensure-live-term terminal)
+ (eat--t-term-end terminal))
+
+(defun eat-term-display-beginning (terminal)
+ "Return the beginning position of TERMINAL's display."
+ (eat--t-ensure-live-term terminal)
+ (eat--t-disp-begin (eat--t-term-display terminal)))
+
+(defun eat-term-display-cursor (terminal)
+ "Return the cursor's current position on TERMINAL's display."
+ (eat--t-ensure-live-term terminal)
+ (let* ((disp (eat--t-term-display terminal))
+ (cursor (eat--t-disp-cursor disp)))
+ ;; The cursor might be after the edge of the display. But we
+ ;; don't want the UI to show that, so show cursor at the edge.
+ (if (> (eat--t-cur-x cursor) (eat--t-disp-width disp))
+ (1- (eat--t-cur-position cursor))
+ (eat--t-cur-position cursor))))
+
+(defun eat-term-title (terminal)
+ "Return the current title of TERMINAL."
+ (eat--t-ensure-live-term terminal)
+ (eat--t-term-title terminal))
+
+(defun eat-term-size (terminal)
+ "Return the size of TERMINAL as (WIDTH . HEIGHT)."
+ (eat--t-ensure-live-term terminal)
+ (let ((disp (eat--t-term-display terminal)))
+ (cons (eat--t-disp-width disp) (eat--t-disp-height disp))))
+
+(defun eat-term-process-output (terminal output)
+ "Process OUTPUT from client and show it on TERMINAL's display."
+ (let ((inhibit-quit t))
+ (eat--t-with-env terminal
+ (eat--t-handle-output output))))
+
+(defun eat-term-redisplay (terminal)
+ "Prepare TERMINAL for displaying."
+ (let ((inhibit-quit t))
+ (eat--t-with-env terminal
+ (let ((disp (eat--t-term-display eat--t-term)))
+ (when (< (eat--t-disp-old-begin disp)
+ (eat--t-disp-begin disp))
+ ;; Join long lines.
+ (let ((limit (copy-marker (1- (eat--t-disp-begin disp)))))
+ (save-excursion
+ (goto-char (max (1- (eat--t-disp-old-begin disp))
+ (point-min)))
+ (while (< (point) limit)
+ (eat--t-join-long-line limit))))
+ ;; Truncate scrollback.
+ (when eat-term-scrollback-size
+ (delete-region
+ (point-min)
+ (max (point-min) (- (point) eat-term-scrollback-size))))
+ (set-marker (eat--t-disp-old-begin disp)
+ (eat--t-disp-begin disp)))))))
+
+(defun eat-term-resize (terminal width height)
+ "Resize TERMINAL to WIDTH x HEIGHT."
+ (let ((inhibit-quit t))
+ (eat--t-with-env terminal
+ (eat--t-resize width height))))
+
+(defun eat-term-in-alternative-display-p (terminal)
+ "Return non-nil when TERMINAL is in alternative display mode."
+ (eat--t-ensure-live-term terminal)
+ (eat--t-term-main-display terminal))
+
+(defun eat-term-input-event (terminal n event &optional ref-pos)
+ "Send EVENT as input N times to TERMINAL.
+
+EVENT should be a event. It can be any standard Emacs event, or a
+event list of any of the following forms:
+
+ (eat-focus-in)
+ Terminal just gained focus.
+
+ (eat-focus-out)
+ Terminal just lost focus.
+
+REF-POS is a mouse position list pointing to the start of terminal
+display satisfying the predicate `posnp'. It is used to calculate the
+position of mouse events and `eat-mouse-drag' events on terminal when
+given.
+
+For mouse events, events should be sent on both mouse button press and
+release unless the mouse grabing mode is `:click', otherwise the
+client process may get confused."
+ (eat--t-ensure-live-term terminal)
+ (let ((disp (eat--t-term-display terminal)))
+ (cl-flet ((send (str)
+ (funcall (eat--t-term-input-fn terminal)
+ terminal str)))
+ (dotimes (_ (or n 1))
+ (pcase event
+ ;; Arrow key, `insert', `delete', `deletechar', `home',
+ ;; `end', `prior', `next' and their modifier variants.
+ ((and (or 'up 'down 'right 'left
+ 'C-up 'C-down 'C-right 'C-left
+ 'M-up 'M-down 'M-right 'M-left
+ 'S-up 'S-down 'S-right 'S-left
+ 'C-M-up 'C-M-down 'C-M-right 'C-M-left
+ 'C-S-up 'C-S-down 'C-S-right 'C-S-left
+ 'M-S-up 'M-S-down 'M-S-right 'M-S-left
+ 'C-M-S-up 'C-M-S-down 'C-M-S-right 'C-M-S-left
+ 'insert 'C-insert 'M-insert 'S-insert 'C-M-insert
+ 'C-S-insert 'M-S-insert 'C-M-S-insert
+ 'delete 'C-delete 'M-delete 'S-delete 'C-M-delete
+ 'C-S-delete 'M-S-delete 'C-M-S-delete
+ 'deletechar 'C-deletechar 'M-deletechar
+ 'S-deletechar 'C-M-deletechar 'C-S-deletechar
+ 'M-S-deletechar 'C-M-S-deletechar
+ 'home 'C-home 'M-home 'S-home 'C-M-home 'C-S-home
+ 'M-S-home 'C-M-S-home
+ 'end 'C-end 'M-end 'S-end 'C-M-end 'C-S-end
+ 'M-S-end 'C-M-S-end
+ 'prior 'C-prior 'M-prior 'S-prior 'C-M-prior
+ 'C-S-prior 'M-S-prior 'C-M-S-prior
+ 'next 'C-next 'M-next 'S-next 'C-M-next 'C-S-next
+ 'M-S-next 'C-M-S-next)
+ ev)
+ (send
+ (format
+ "\e%s%c"
+ (if (not (or (memq 'control (event-modifiers ev))
+ (memq 'meta (event-modifiers ev))
+ (memq 'shift (event-modifiers ev))))
+ (pcase (event-basic-type ev)
+ ('insert "[2")
+ ((or 'delete 'deletechar) "[3")
+ ('prior "[5")
+ ('next "[6")
+ (_ (if (eat--t-term-keypad-mode terminal)
+ "O"
+ "[")))
+ (format
+ "[%c;%c"
+ (pcase (event-basic-type ev)
+ ('insert ?2)
+ ((or 'delete 'deletechar) ?3)
+ ('prior ?5)
+ ('next ?6)
+ (_ ?1))
+ (pcase-exhaustive (event-modifiers ev)
+ ((and (pred (memq 'control))
+ (pred (memq 'meta))
+ (pred (memq 'shift)))
+ ?8)
+ ((and (pred (memq 'control))
+ (pred (memq 'meta)))
+ ?7)
+ ((and (pred (memq 'control))
+ (pred (memq 'shift)))
+ ?6)
+ ((and (pred (memq 'meta))
+ (pred (memq 'shift)))
+ ?4)
+ ((pred (memq 'control))
+ ?5)
+ ((pred (memq 'meta))
+ ?3)
+ ((pred (memq 'shift))
+ ?2))))
+ (pcase (event-basic-type ev)
+ ('up ?A)
+ ('down ?B)
+ ('right ?C)
+ ('left ?D)
+ ('home ?H)
+ ('end ?F)
+ (_ ?~)))))
+ ((or 'backspace ?\C-?)
+ (send "\C-?"))
+ ('C-backspace
+ (send "\C-h"))
+ ((or 'M-backspace
+ (pred (lambda (ev)
+ (and (equal (event-basic-type ev) ?\C-?)
+ (equal (event-modifiers ev) '(meta))))))
+ (send "\e\C-?"))
+ ('C-M-backspace
+ (send "\e\C-h"))
+ ('tab
+ (send "\t"))
+ ('backtab
+ (send "\e[Z"))
+ ;; Function keys.
+ ((and (pred symbolp)
+ fn-key
+ (let (rx string-start "f"
+ (let fn-num (one-or-more (any (?0 . ?9))))
+ string-end)
+ (symbol-name fn-key))
+ (let (and (pred (<= 1))
+ (pred (>= 63))
+ key)
+ (string-to-number fn-num)))
+ (send
+ (aref
+ ["\eOP" "\eOQ" "\eOR" "\eOS" "\e[15~" "\e[17~" "\e[18~"
+ "\e[19~" "\e[20~" "\e[21~" "\e[23~" "\e[24~" "\e[1;2P"
+ "\e[1;2Q" "\e[1;2R" "\e[1;2S" "\e[15;2~" "\e[17;2~"
+ "\e[18;2~" "\e[19;2~" "\e[20;2~" "\e[21;2~" "\e[23;2~"
+ "\e[24;2~" "\e[1;5P" "\e[1;5Q" "\e[1;5R" "\e[1;5S"
+ "\e[15;5~" "\e[17;5~" "\e[18;5~" "\e[19;5~" "\e[20;5~"
+ "\e[21;5~" "\e[23;5~" "\e[24;5~" "\e[1;6P" "\e[1;6Q"
+ "\e[1;6R" "\e[1;6S" "\e[15;6~" "\e[17;6~" "\e[18;6~"
+ "\e[19;6~" "\e[20;6~" "\e[21;6~" "\e[23;6~" "\e[24;6~"
+ "\e[1;3P" "\e[1;3Q" "\e[1;3R" "\e[1;3S" "\e[15;3~"
+ "\e[17;3~" "\e[18;3~" "\e[19;3~" "\e[20;3~" "\e[21;3~"
+ "\e[23;3~" "\e[24;3~" "\e[1;4P" "\e[1;4Q" "\e[1;4R"]
+ (1- key))))
+ ((and (or (pred numberp)
+ (pred symbolp))
+ char)
+ ;; Adapted from Term source.
+ (when (symbolp char)
+ ;; Convert `return' to C-m, etc.
+ (let ((tmp (get char 'event-symbol-elements)))
+ (when tmp
+ (setq char (car tmp)))
+ (and (symbolp char)
+ (setq tmp (get char 'ascii-character))
+ (setq char tmp))))
+ (when (numberp char)
+ (let ((base (event-basic-type char))
+ (mods (event-modifiers char)))
+ ;; Try to avoid event-convert-list if possible.
+ (if (and (characterp char)
+ (not (memq 'meta mods))
+ (not (and (memq 'control mods)
+ (memq 'shift mods))))
+ (send (format "%c" char))
+ (when (memq 'control mods)
+ (setq mods (delq 'shift mods)))
+ (let ((ch (pcase (event-convert-list
+ (append (remq 'meta mods)
+ (list base)))
+ (?\C-\s ?\C-@)
+ (?\C-/ ?\C-?)
+ (?\C-- ?\C-_)
+ (c c))))
+ (when (characterp ch)
+ (send (cond
+ ((and (memq 'meta mods)
+ (memq ch '(?\[ ?O)))
+ "\e")
+ (t
+ (format
+ (if (memq 'meta mods) "\e%c" "%c")
+ ch))))))))))
+ ;; Mouse handling.
+ ((and (guard (eat--t-term-mouse-mode terminal))
+ mouse
+ (pred eventp)
+ (or (and (let mouse-type (event-basic-type mouse))
+ (let (rx string-start "mouse-"
+ (let key-num (one-or-more
+ (any (?0 . ?9))))
+ string-end)
+ (symbol-name mouse-type))
+ (let (and (pred (<= 1))
+ (pred (>= 11))
+ mouse-num)
+ (string-to-number key-num)))
+ (and (let 'wheel-up (event-basic-type mouse))
+ (let mouse-num 4))
+ (and (let 'wheel-down (event-basic-type mouse))
+ (let mouse-num 5))
+ (and (let 'wheel-right (event-basic-type mouse))
+ (let mouse-num 6))
+ (and (let 'wheel-left (event-basic-type mouse))
+ (let mouse-num 7))))
+ (let* ((modifiers (event-modifiers mouse))
+ (pos (if (memq 'drag modifiers)
+ (event-end mouse)
+ (event-start mouse)))
+ (x-y (if (eval-when-compile
+ (< emacs-major-version 29))
+ (posn-col-row pos)
+ (with-suppressed-warnings
+ ((callargs posn-col-row))
+ (posn-col-row pos 'use-window))))
+ (x (1+ (car x-y)))
+ (y (1+ (cdr x-y)))
+ (button
+ (let ((b (aref
+ [0 1 2 64 65 66 67 128 129 130 131]
+ (1- mouse-num))))
+ (when (memq 'shift modifiers)
+ (cl-incf b 4))
+ (when (memq 'meta modifiers)
+ (cl-incf b 8))
+ (when (memq 'control modifiers)
+ (cl-incf b 16))
+ b)))
+ (when ref-pos
+ (let ((ref-x-y
+ (if (eval-when-compile
+ (< emacs-major-version 29))
+ (posn-col-row ref-pos)
+ (with-suppressed-warnings
+ ((callargs posn-col-row))
+ (posn-col-row ref-pos 'use-window)))))
+ (cl-decf x (car ref-x-y))
+ (cl-decf y (cdr ref-x-y))))
+ (when (and (<= 1 x (eat--t-disp-width disp))
+ (<= 1 y (eat--t-disp-height disp))
+ (or (eat--t-term-mouse-encoding terminal)
+ (and (<= x 95)
+ (<= y 95)
+ (<= button 95))))
+ (if (eq (eat--t-term-mouse-mode terminal) 'x10)
+ (when (and (< button 3)
+ (or (memq 'click modifiers)
+ (memq 'drag modifiers)))
+ (send
+ (if (eq (eat--t-term-mouse-encoding terminal)
+ 'sgr)
+ (format "\e[<%i;%i;%iM" button x y)
+ (format "\e[M%c%c%c" (+ button 32) (+ x 32)
+ (+ y 32)))))
+ (cond
+ ;; `down-mouse-1' and friends.
+ ((memq 'down modifiers)
+ ;; For `mouse-1', `mouse-2' and `mouse-3', keep
+ ;; track the button's state, we'll need it when
+ ;; button event mouse mode is enabled.
+ (when (< (logand button 3) 3)
+ (setf (eat--t-term-mouse-pressed terminal)
+ ;; In XTerm and Kitty, mouse-1 is
+ ;; prioritized over mouse-2, and mouse-2
+ ;; over mouse-3. However St doesn't keep
+ ;; track of multiple buttons.
+ (sort
+ (cons button (eat--t-term-mouse-pressed
+ terminal))
+ #'<)))
+ (send
+ (if (eq (eat--t-term-mouse-encoding terminal)
+ 'sgr)
+ (format "\e[<%i;%i;%iM" button x y)
+ (format "\e[M%c%c%c" (+ button 32) (+ x 32)
+ (+ y 32)))))
+ ;; `mouse-1', `mouse-2', `mouse-3', and their
+ ;; `drag'ged variants.
+ ((and (or (memq 'click modifiers)
+ (memq 'drag modifiers))
+ (<= mouse-num 3))
+ ;; For `mouse-1', `mouse-2' and `mouse-3', keep
+ ;; track the button's state, we'll need it when
+ ;; button event mouse mode is enabled.
+ (setf (eat--t-term-mouse-pressed terminal)
+ (cl-delete-if
+ (lambda (b)
+ (= (logand b 3) (logand button 3)))
+ (eat--t-term-mouse-pressed terminal)))
+ (send
+ (if (eq (eat--t-term-mouse-encoding terminal)
+ 'sgr)
+ (format "\e[<%i;%i;%im" button x y)
+ (format "\e[M%c%c%c" (+ (logior button 3) 32)
+ (+ x 32) (+ y 32)))))
+ ;; Mouse wheel, `mouse-4' and friends.
+ (t
+ (send
+ (if (eq (eat--t-term-mouse-encoding terminal)
+ 'sgr)
+ (format "\e[<%i;%i;%iM" button x y)
+ (format "\e[M%c%c%c" (+ button 32) (+ x 32)
+ (+ y 32))))))))))
+ ;; Mouse movement tracking.
+ ((and (guard (memq (eat--t-term-mouse-mode terminal)
+ '(button-event any-event)))
+ (pred mouse-movement-p)
+ movement)
+ (let* ((pos (event-start movement))
+ (x-y (if (eval-when-compile
+ (< emacs-major-version 29))
+ (posn-col-row pos)
+ (with-suppressed-warnings
+ ((callargs posn-col-row))
+ (posn-col-row pos 'use-window))))
+ (x (1+ (car x-y)))
+ (y (1+ (cdr x-y)))
+ (button
+ (if (car (eat--t-term-mouse-pressed terminal))
+ (+ (car (eat--t-term-mouse-pressed terminal))
+ 32)
+ 35)))
+ (when ref-pos
+ (let ((ref-x-y
+ (if (eval-when-compile
+ (< emacs-major-version 29))
+ (posn-col-row ref-pos)
+ (with-suppressed-warnings
+ ((callargs posn-col-row))
+ (posn-col-row ref-pos 'use-window)))))
+ (cl-decf x (car ref-x-y))
+ (cl-decf y (cdr ref-x-y))))
+ (when (and (or (eq (eat--t-term-mouse-mode terminal)
+ 'any-event)
+ (/= button 35))
+ (<= 1 x (eat--t-disp-width disp))
+ (<= 1 y (eat--t-disp-height disp))
+ (or (eat--t-term-mouse-encoding terminal)
+ (and (<= x 95)
+ (<= y 95)
+ (<= button 95))))
+ (send
+ (if (eq (eat--t-term-mouse-encoding terminal)
+ 'sgr)
+ (format "\e[<%i;%i;%iM" button x y)
+ (format "\e[M%c%c%c" (+ button 32) (+ x 32)
+ (+ y 32)))))))
+ ;; Focus events.
+ ('(eat-focus-in)
+ (when (eat--t-term-focus-event-mode terminal)
+ (send "\e[I")))
+ ('(eat-focus-out)
+ (when (eat--t-term-focus-event-mode terminal)
+ (send "\e[O"))))))))
+
+(defun eat-term-send-string (terminal string)
+ "Send STRING to TERMINAL directly."
+ (eat--t-ensure-live-term terminal)
+ (funcall (eat--t-term-input-fn terminal) terminal string))
+
+(defun eat-term-send-string-as-yank (terminal args)
+ "Send ARGS to TERMINAL, honoring bracketed yank mode.
+
+Each argument in ARGS can be either string or character."
+ (eat--t-ensure-live-term terminal)
+ (funcall (eat--t-term-input-fn terminal) terminal
+ (let ((str (mapconcat (lambda (s)
+ (if (stringp s) s (string s)))
+ args "")))
+ (if (eat--t-term-bracketed-yank terminal)
+ ;; REVIEW: What if `str' itself contains these escape
+ ;; sequences? St doesn't care and just wraps the
+ ;; string with these magic escape sequences, while
+ ;; Kitty tries to be smart.
+ (format "\e[200~%s\e[201~" str)
+ str))))
+
+(defun eat-term-make-keymap (input-command categories exceptions)
+ "Make a keymap binding INPUT-COMMAND to the events of CATEGORIES.
+
+CATEGORIES is a list whose elements should be a one of the following
+keywords:
+
+ `:ascii' All self-insertable characters, plus
+ `backspace', `DEL', `insert', `delete' and
+ `deletechar' keys, with all possible
+ modifiers.
+ `:arrow' Arrow keys with all possible modifiers.
+ `:navigation' Navigation keys: home, end, prior (or page up)
+ and next (or page down) with all possible
+ modifiers.
+ `:function' Function keys (f1 - f63).
+ `:mouse-click' `mouse-1', `mouse-2' and `mouse-3'.
+ `:mouse-modifier' All mouse events except mouse movement.
+ `:mouse-movement' Mouse movement.
+
+EXCEPTIONS is a list of key sequences to not bind. Don't use
+\"M-...\" key sequences in EXCEPTIONS, use \"ESC ...\" instead."
+ (let ((map (make-sparse-keymap)))
+ (cl-flet ((bind (key)
+ (unless (member key exceptions)
+ (define-key map key input-command))))
+ (when (memq :ascii categories)
+ ;; Bind ASCII and self-insertable characters except ESC.
+ (bind [remap self-insert-command])
+ (cl-loop
+ for i from ?\C-@ to ?\C-?
+ do (unless (= i meta-prefix-char)
+ (bind (vector i))))
+ ;; Bind `tab', `backspace', `delete', `deletechar', and all
+ ;; modified variants.
+ (dolist (key '( tab backtab backspace C-backspace
+ M-backspace C-M-backspace
+ insert C-insert M-insert S-insert C-M-insert
+ C-S-insert M-S-insert C-M-S-insert
+ delete C-delete M-delete S-delete C-M-delete
+ C-S-delete M-S-delete C-M-S-delete
+ deletechar C-deletechar M-deletechar
+ S-deletechar C-M-deletechar C-S-deletechar
+ M-S-deletechar C-M-S-deletechar))
+ (bind (vector key)))
+ ;; Bind these non-encodable keys. They are translated.
+ (dolist (key '(?\C-- ?\C-? ?\C-\s))
+ (bind (vector key)))
+ ;; Bind M-<ASCII> keys.
+ (unless (member (vector meta-prefix-char) exceptions)
+ (define-key map (vector meta-prefix-char)
+ (make-sparse-keymap))
+ (cl-loop
+ for i from ?\C-@ to ?\C-?
+ do (unless (memq i '(?O ?\[))
+ (bind (vector meta-prefix-char i))))
+ (bind (vector meta-prefix-char meta-prefix-char))))
+ (when (memq :arrow categories)
+ (dolist (key '( up down right left
+ C-up C-down C-right C-left
+ M-up M-down M-right M-left
+ S-up S-down S-right S-left
+ C-M-up C-M-down C-M-right C-M-left
+ C-S-up C-S-down C-S-right C-S-left
+ M-S-up M-S-down M-S-right M-S-left
+ C-M-S-up C-M-S-down C-M-S-right C-M-S-left))
+ (bind (vector key))))
+ (when (memq :navigation categories)
+ (dolist (key '( home C-home M-home S-home C-M-home C-S-home
+ M-S-home C-M-S-home
+ end C-end M-end S-end C-M-end C-S-end
+ M-S-end C-M-S-end
+ prior C-prior M-prior S-prior C-M-prior
+ C-S-prior M-S-prior C-M-S-prior
+ next C-next M-next S-next C-M-next C-S-next
+ M-S-next C-M-S-next))
+ (bind (vector key))))
+ (when (memq :function categories)
+ (cl-loop
+ for i from 1 to 63
+ do (let ((key (intern (format "f%i" i))))
+ (bind (vector key)))))
+ (when (memq :mouse-click categories)
+ (dolist (key '(mouse-1 mouse-2 mouse-3))
+ (bind (vector key))))
+ (when (memq :mouse-modifier categories)
+ (dolist (key
+ '( down-mouse-1 drag-mouse-1 down-mouse-2
+ drag-mouse-2 down-mouse-3 drag-mouse-3
+ C-down-mouse-1 C-drag-mouse-1 C-down-mouse-2
+ C-drag-mouse-2 C-down-mouse-3 C-drag-mouse-3
+ M-down-mouse-1 M-drag-mouse-1 M-down-mouse-2
+ M-drag-mouse-2 M-down-mouse-3 M-drag-mouse-3
+ S-down-mouse-1 S-drag-mouse-1 S-down-mouse-2
+ S-drag-mouse-2 S-down-mouse-3 S-drag-mouse-3
+ C-M-down-mouse-1 C-M-drag-mouse-1
+ C-M-down-mouse-2 C-M-drag-mouse-2
+ C-M-down-mouse-3 C-M-drag-mouse-3
+ C-S-down-mouse-1 C-S-drag-mouse-1
+ C-S-down-mouse-2 C-S-drag-mouse-2
+ C-S-down-mouse-3 C-S-drag-mouse-3
+ M-S-down-mouse-1 M-S-drag-mouse-1
+ M-S-down-mouse-2 M-S-drag-mouse-2
+ M-S-down-mouse-3 M-S-drag-mouse-3
+ C-M-S-down-mouse-1 C-M-S-drag-mouse-1
+ C-M-S-down-mouse-2 C-M-S-drag-mouse-2
+ C-M-S-down-mouse-3 C-M-S-drag-mouse-3 mouse-1
+ mouse-2 mouse-3 mouse-4 mouse-5 mouse-6 mouse-7
+ mouse-8 mouse-9 mouse-10 mouse-11 C-mouse-1
+ C-mouse-2 C-mouse-3 C-mouse-4 C-mouse-5
+ C-mouse-6 C-mouse-7 C-mouse-8 C-mouse-9
+ C-mouse-10 C-mouse-11 M-mouse-1 M-mouse-2
+ M-mouse-3 M-mouse-4 M-mouse-5 M-mouse-6
+ M-mouse-7 M-mouse-8 M-mouse-9 M-mouse-10
+ M-mouse-11 S-mouse-1 S-mouse-2 S-mouse-3
+ S-mouse-4 S-mouse-5 S-mouse-6 S-mouse-7
+ S-mouse-8 S-mouse-9 S-mouse-10 S-mouse-11
+ C-M-mouse-1 C-M-mouse-2 C-M-mouse-3 C-M-mouse-4
+ C-M-mouse-5 C-M-mouse-6 C-M-mouse-7 C-M-mouse-8
+ C-M-mouse-9 C-M-mouse-10 C-M-mouse-11
+ C-S-mouse-1 C-S-mouse-2 C-S-mouse-3 C-S-mouse-4
+ C-S-mouse-5 C-S-mouse-6 C-S-mouse-7 C-S-mouse-8
+ C-S-mouse-9 C-S-mouse-10 C-S-mouse-11
+ M-S-mouse-1 M-S-mouse-2 M-S-mouse-3 M-S-mouse-4
+ M-S-mouse-5 M-S-mouse-6 M-S-mouse-7 M-S-mouse-8
+ M-S-mouse-9 M-S-mouse-10 M-S-mouse-11
+ C-M-S-mouse-1 C-M-S-mouse-2 C-M-S-mouse-3
+ C-M-S-mouse-4 C-M-S-mouse-5 C-M-S-mouse-6
+ C-M-S-mouse-7 C-M-S-mouse-8 C-M-S-mouse-9
+ C-M-S-mouse-10 C-M-S-mouse-11 wheel-up
+ wheel-down wheel-right wheel-left C-wheel-up
+ C-wheel-down C-wheel-right C-wheel-left
+ M-wheel-up M-wheel-down M-wheel-right
+ M-wheel-left S-wheel-up S-wheel-down
+ S-wheel-right S-wheel-left C-M-wheel-up
+ C-M-wheel-down C-M-wheel-right C-M-wheel-left
+ C-S-wheel-up C-S-wheel-down C-S-wheel-right
+ C-S-wheel-left M-S-wheel-up M-S-wheel-down
+ M-S-wheel-right M-S-wheel-left C-M-S-wheel-up
+ C-M-S-wheel-down C-M-S-wheel-right
+ C-M-S-wheel-left))
+ (bind (vector key))))
+ (when (memq :mouse-movement categories)
+ (bind [mouse-movement])))
+ map))
+
+(defun eat-term-name ()
+ "Return the value of `TERM' environment variable for Eat."
+ (if (stringp eat-term-name)
+ eat-term-name
+ (funcall eat-term-name)))
+
+(defun eat-term-get-suitable-term-name (&optional display)
+ "Return the most suitable value for `TERM' for DISPLAY.
+
+If the number of colors supported by display (as returned by
+`display-color-cells') is more than 256, return \"eat-truecolor\", if
+it is more than 8 but less than or equal to 256, return
+\"eat-256color\", if is more than 1 but less than or equal to 8,
+return \"eat-color\", otherwise return \"eat-mono\"."
+ (let ((colors (display-color-cells display)))
+ (cond ((> colors 256) "eat-truecolor")
+ ((> colors 8) "eat-256color")
+ ((> colors 1) "eat-color")
+ (t "eat-mono"))))
+
+(defun eat-term-filter-string (string)
+ "Filter Eat's special text properties from STRING."
+ (with-temp-buffer
+ (insert string)
+ ;; Join long lines.
+ (goto-char (point-min))
+ (while (not (eobp))
+ (eat--t-join-long-line))
+ ;; Remove the invisible spaces used with multi-column characters.
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let ((invisible-p (get-text-property
+ (point) 'eat--t-invisible-space))
+ (next-change (or (next-single-property-change
+ (point) 'eat--t-invisible-space)
+ (point-max))))
+ (when invisible-p
+ (delete-region (point) next-change))
+ (goto-char next-change)))
+ (remove-text-properties (point-min) (point-max)
+ '( eat--t-char-width nil
+ eat--t-sixel-bitmap-size nil
+ eat--t-sixel-bitmap nil))
+ (buffer-string)))
+
+\f
+;;;; Blink mode.
+
+(defvar eat--slow-blink-state nil
+ "Current state of slowly blinking text, t means inverse video.")
+
+(defvar eat--fast-blink-state nil
+ "Current state of rapidly blinking text, t means inverse video.")
+
+(defvar eat--slow-blink-remap nil
+ "Face remapping cookie of slowly blinking face.")
+
+(defvar eat--fast-blink-remap nil
+ "Face remapping cookie of rapidly blinking face.")
+
+(defvar eat--slow-blink-timer nil
+ "Timer for blinking slowly blinking text.")
+
+(defvar eat--fast-blink-timer nil
+ "Timer for blinking rapidly blinking text.")
+
+(declare-function face-remap-add-relative "face-remap"
+ (face &rest specs))
+(declare-function face-remap-remove-relative "face-remap" (cookie))
+
+(defun eat--flip-slow-blink-state ()
+ "Flip the state of slowly blinking text."
+ (face-remap-remove-relative eat--slow-blink-remap)
+ (setq eat--slow-blink-remap
+ (face-remap-add-relative
+ 'eat-slow-blink
+ `(:box nil :inverse-video ,(not eat--slow-blink-state)))
+ eat--slow-blink-state (not eat--slow-blink-state)))
+
+(defun eat--flip-fast-blink-state ()
+ "Flip the state of rapidly blinking text."
+ (face-remap-remove-relative eat--fast-blink-remap)
+ (setq eat--fast-blink-remap
+ (face-remap-add-relative
+ 'eat-fast-blink
+ `(:box nil :inverse-video ,(not eat--fast-blink-state)))
+ eat--fast-blink-state (not eat--fast-blink-state)))
+
+(defun eat--blink-stop-timers ()
+ "Start blinking timers."
+ (when eat--slow-blink-timer
+ (cancel-timer eat--slow-blink-timer)
+ (setq eat--slow-blink-timer nil))
+ (when eat--fast-blink-timer
+ (cancel-timer eat--fast-blink-timer)
+ (setq eat--fast-blink-timer nil)))
+
+(defun eat--blink-start-timers ()
+ "Start blinking timers."
+ (eat--blink-stop-timers)
+ (setq eat--slow-blink-timer
+ (run-with-timer t (/ (float eat-slow-blink-frequency))
+ #'eat--flip-slow-blink-state))
+ (setq eat--fast-blink-timer
+ (run-with-timer t (/ (float eat-fast-blink-frequency))
+ #'eat--flip-fast-blink-state)))
+
+(define-minor-mode eat-blink-mode
+ "Toggle blinking of text with blink attribute."
+ :lighter " Eat-Blink"
+ (let ((locals '( eat--slow-blink-state eat--fast-blink-state
+ eat--slow-blink-remap eat--fast-blink-remap
+ eat--slow-blink-timer eat--fast-blink-timer)))
+ (cond
+ (eat-blink-mode
+ (setq eat-blink-mode nil)
+ (require 'face-remap)
+ (setq eat-blink-mode t)
+ (mapc #'make-local-variable locals)
+ (setq eat--slow-blink-state nil)
+ (setq eat--fast-blink-state nil)
+ (setq eat--slow-blink-remap
+ (face-remap-add-relative 'eat-term-slow-blink
+ '(:box nil)))
+ (setq eat--fast-blink-remap
+ (face-remap-add-relative 'eat-term-fast-blink
+ '(:box nil)))
+ (add-hook 'pre-command-hook #'eat--blink-stop-timers nil t)
+ (add-hook 'post-command-hook #'eat--blink-start-timers nil t))
+ (t
+ (eat--blink-stop-timers)
+ (face-remap-remove-relative eat--slow-blink-remap)
+ (face-remap-remove-relative eat--fast-blink-remap)
+ (remove-hook 'pre-command-hook #'eat--blink-stop-timers t)
+ (remove-hook 'post-command-hook #'eat--blink-start-timers t)
+ (mapc #'kill-local-variable locals)))))
+
+\f
+;;;; Buffer-local Cursor Blinking.
+
+(defvar eat--cursor-blink-type nil
+ "Type of blinking cursor.")
+
+(defvar eat--cursor-blink-state nil
+ "Current state of slowly blinking text, non-nil means on.")
+
+(defvar eat--cursor-blink-timer nil
+ "Timer for blinking slowly blinking text.")
+
+(defvar eat--cursor-blink-mode)
+
+(defun eat--flip-cursor-blink-state ()
+ "Flip the state of slowly blinking text."
+ (when (and eat--cursor-blink-mode
+ (display-graphic-p))
+ (setq-local cursor-type (if eat--cursor-blink-state
+ (caddr eat--cursor-blink-type)
+ (car eat--cursor-blink-type)))
+ (setq eat--cursor-blink-state (not eat--cursor-blink-state))
+ ;; REVIEW: This is expensive, and some causes flickering. Any
+ ;; better way?
+ (when-let* ((window (get-buffer-window nil 'visible)))
+ (redraw-frame (window-frame window)))))
+
+(defun eat--cursor-blink-stop-timers ()
+ "Stop blinking timers."
+ (unless eat--cursor-blink-state
+ (eat--flip-cursor-blink-state))
+ (when eat--cursor-blink-timer
+ (cancel-timer eat--cursor-blink-timer)
+ (setq eat--cursor-blink-timer nil)))
+
+(defun eat--cursor-blink-start-timers ()
+ "Start blinking timers."
+ (eat--cursor-blink-stop-timers)
+ (setq eat--cursor-blink-timer
+ (run-with-timer t (/ (float (cadr eat--cursor-blink-type)))
+ #'eat--flip-cursor-blink-state)))
+
+(define-minor-mode eat--cursor-blink-mode
+ "Toggle blinking of cursor."
+ :interactive nil
+ (let ((locals '(eat--cursor-blink-state eat--cursor-blink-timer)))
+ (cond
+ (eat--cursor-blink-mode
+ (mapc #'make-local-variable locals)
+ (setq eat--cursor-blink-state nil)
+ (setq eat--cursor-blink-timer nil)
+ (add-hook 'pre-command-hook #'eat--cursor-blink-stop-timers nil
+ t)
+ (add-hook 'post-command-hook #'eat--cursor-blink-start-timers
+ nil t)
+ (add-hook 'kill-buffer-hook #'eat--cursor-blink-stop-timers nil
+ t)
+ (when (current-idle-time)
+ (eat--cursor-blink-start-timers)))
+ (t
+ (eat--cursor-blink-stop-timers)
+ (remove-hook 'pre-command-hook #'eat--cursor-blink-stop-timers
+ t)
+ (remove-hook 'post-command-hook #'eat--cursor-blink-start-timers
+ t)
+ (remove-hook 'kill-buffer-hook #'eat--cursor-blink-stop-timers
+ t)
+ (mapc #'kill-local-variable locals)))))
+
+\f
+;;;; User Interface.
+
+(defvar eat-terminal nil
+ "The terminal emulator.")
+
+(defvar eat--synchronize-scroll-function nil
+ "Function to synchronize scrolling between terminal and window.")
+
+(defvar eat--shell-command-status 0
+ "If the current shell command has finished, its exit status.")
+
+(defvar eat--shell-prompt-begin nil
+ "Beginning of last shell prompt.")
+
+(defvar eat--shell-prompt-mark nil
+ "Display property used to put a mark before the previous prompt.")
+
+(defvar eat--shell-prompt-mark-overlays nil
+ "List of overlay used to put marks before shell prompts.")
+
+(defvar eat--inhibit-auto-line-mode nil
+ "Non-nil means don't enter line mode.")
+
+(defvar eat--auto-line-mode-prev-mode nil
+ "The input mode active before line mode.")
+
+(defvar eat--auto-line-mode-pending-toggles nil
+ "Automatic line mode toggles left to do.
+
+Don't change the toplevel value of this, let-bind instead.")
+
+(defun eat-reset ()
+ "Perform a terminal reset."
+ (interactive)
+ (when eat-terminal
+ (let ((inhibit-read-only t))
+ (eat-term-reset eat-terminal)
+ (eat-term-redisplay eat-terminal))
+ (run-hooks 'eat-update-hook)))
+
+(defun eat--set-cursor (_ state)
+ "Set cursor type according to STATE.
+
+STATE can be one of the following:
+
+ `:invisible' Invisible cursor.
+ `:block' Block (filled box) cursor (default).
+ `:blinking-block' Blinking block cursor.
+ `:bar' Vertical bar cursor.
+ `:blinking-bar' Blinking vertical bar cursor.
+ `:underline' Horizontal bar cursor.
+ `:blinking-underline' Blinking horizontal bar cursor.
+ Any other value Block cursor."
+ (setq-local
+ eat--cursor-blink-type
+ (pcase state
+ (:invisible eat-invisible-cursor-type)
+ (:block eat-default-cursor-type)
+ (:blinking-block eat-very-visible-cursor-type)
+ (:bar eat-vertical-bar-cursor-type)
+ (:blinking-bar eat-very-visible-vertical-bar-cursor-type)
+ (:underline eat-horizontal-bar-cursor-type)
+ (:blinking-underline eat-very-visible-horizontal-bar-cursor-type)
+ (_ eat-default-cursor-type)))
+ (setq-local cursor-type (car eat--cursor-blink-type))
+ (when (xor (cadr eat--cursor-blink-type) eat--cursor-blink-mode)
+ (eat--cursor-blink-mode
+ (if (cadr eat--cursor-blink-type) +1 -1))))
+
+(defun eat--manipulate-kill-ring (_ selection data)
+ "Manipulate `kill-ring'.
+
+SELECTION can be one of `:clipboard', `:primary', `:secondary',
+`:select'. When DATA is a string, set the selection to that string,
+when DATA is nil, unset the selection, and when DATA is t, return the
+selection, or nil if none."
+ (let ((inhibit-eol-conversion t)
+ (select-enable-clipboard (eq selection :clipboard))
+ (select-enable-primary (eq selection :primary)))
+ (pcase-exhaustive data
+ ('t
+ (when eat-enable-yank-to-terminal
+ (ignore-error error
+ (current-kill 0 'do-not-move))))
+ ('nil
+ (when eat-enable-kill-from-terminal
+ (kill-new "")))
+ ((and (pred stringp) str)
+ (when eat-enable-kill-from-terminal
+ (kill-new str))))))
+
+(defun eat--bell (_)
+ "Ring the bell."
+ (ding t))
+
+(defun eat--sixel-render-format ()
+ "Return the suitable Sixel render format."
+ (cl-block nil
+ (dolist (fmt eat-sixel-render-formats)
+ (pcase-exhaustive fmt
+ ('none (cl-return 'none))
+ ('background (cl-return 'background))
+ ('half-block (when (char-displayable-p ?▄)
+ (cl-return 'half-block)))
+ ('svg (when (and (display-graphic-p)
+ (image-type-available-p 'svg))
+ (cl-return 'svg)))
+ ('xpm (when (and (display-graphic-p)
+ (image-type-available-p 'xpm))
+ (cl-return 'xpm)))))
+ 'none))
+
+(defun eat--set-term-sixel-params ()
+ "Set Sixel related parameters of the terminal."
+ (let* ((render-fmt (eat--sixel-render-format))
+ (dimensions
+ (pcase render-fmt
+ ((or 'background 'none) '(1 . 1))
+ ('half-block '(1 . 2))
+ (_ (cons (default-font-width) (default-font-height)))))
+ (scale-x (* eat-sixel-aspect-ratio eat-sixel-scale))
+ (scale-y eat-sixel-scale))
+ (setq dimensions
+ (cons (max 1 (round (/ (car dimensions) (float scale-x))))
+ (max 1 (round (/ (cdr dimensions) (float scale-y))))))
+ (setf (eat-term-parameter eat-terminal 'sixel-render-format)
+ render-fmt)
+ (setf (eat-term-parameter eat-terminal 'char-dimensions)
+ dimensions)
+ (unless (memq render-fmt '(none background half-block))
+ (let ((font-size
+ (font-get (font-spec :name (face-font 'default))
+ :size)))
+ (setf
+ (eat-term-parameter eat-terminal
+ 'sixel-image-extra-properties)
+ `( :ascent center
+ :height ,(cons (/ (float (default-font-height)) font-size)
+ 'em)
+ :width ,(cons (/ (float (default-font-width)) font-size)
+ 'em)))))))
+
+(defun eat--set-cwd (_ host cwd)
+ "Set CWD as the current working directory (`default-directory').
+
+If HOST isn't the host Emacs is running on, don't do anything."
+ (when (and eat-enable-directory-tracking
+ (string= host (system-name)))
+ (ignore-errors
+ (cd-absolute cwd))))
+
+(defun eat--set-cwd-uic (host path)
+ "Set PATH to the CWD, if HOST is same as the host name."
+ (let ((dir (ignore-errors (expand-file-name
+ (file-name-as-directory
+ (decode-coding-string
+ (base64-decode-string path)
+ locale-coding-system)))))
+ (hostname (ignore-errors (decode-coding-string
+ (base64-decode-string host)
+ locale-coding-system))))
+ (when (and dir hostname)
+ (eat--set-cwd nil hostname dir))))
+
+(defun eat--pre-prompt ()
+ "Save the beginning position of shell prompt."
+ (setq eat--shell-prompt-begin (point-marker))
+ ;; FIXME: It's a crime to touch processes in this section.
+ (when (eq eat-query-before-killing-running-terminal 'auto)
+ (set-process-query-on-exit-flag
+ (eat-term-parameter eat-terminal 'eat--process) nil)))
+
+(defvar eat--line-mode)
+(defvar eat--semi-char-mode)
+(defvar eat--char-mode)
+
+(defun eat--line-mode-enter-auto-1 ()
+ "Enter line mode."
+ (unless (or eat--inhibit-auto-line-mode eat--line-mode)
+ (unless eat--line-mode
+ (setq eat--auto-line-mode-prev-mode
+ (cond (eat--semi-char-mode 'semi-char)
+ (eat--char-mode 'char)
+ (t 'emacs)))
+ (eat-line-mode)
+ ;; We're entering automatically, so we should be able to exit it
+ ;; automatically.
+ (setq eat--inhibit-auto-line-mode nil))))
+
+(defun eat--line-mode-enter-auto ()
+ "Arrange that line mode will be enabled eventually."
+ (push 'enter eat--auto-line-mode-pending-toggles))
+
+(defun eat--line-mode-exit-auto-1 ()
+ "Exit line mode."
+ (when (and (not eat--inhibit-auto-line-mode)
+ eat--auto-line-mode-prev-mode)
+ (pcase eat--auto-line-mode-prev-mode
+ ('emacs (eat-emacs-mode))
+ ('semi-char (eat-semi-char-mode))
+ ('char (eat-char-mode)))
+ (setq eat--auto-line-mode-prev-mode nil)
+ (when (/= (eat-term-end eat-terminal) (point-max))
+ (eat-line-send))
+ ;; Toggle line mode _after_ we exit from
+ ;; `eat-term-process-output'.
+ (eat--line-mode -1)
+ (setq buffer-undo-list nil)))
+
+(defun eat--line-mode-exit-auto ()
+ "Arrange that line mode will be disabled eventually."
+ (push 'exit eat--auto-line-mode-pending-toggles))
+
+(defun eat--line-mode-do-toggles ()
+ "Do the pending line mode toggle."
+ (let* ((inhibit-quit t)
+ (actions (nreverse eat--auto-line-mode-pending-toggles))
+ (toggle nil))
+ (while (setq toggle (pop actions))
+ (pcase-exhaustive toggle
+ ('enter (eat--line-mode-enter-auto-1))
+ ('exit (eat--line-mode-exit-auto-1)))
+ ;; Don't do extra unnecessary toggles.
+ (let ((loop t))
+ (while loop
+ (setq loop nil)
+ (while (eq toggle (car actions))
+ (pop actions))
+ (while (and (car actions) (cadr actions)
+ (not (eq (car actions) (cadr actions))))
+ (pop actions)
+ (pop actions)
+ (setq loop t)))))
+ (setq eat--auto-line-mode-pending-toggles nil)))
+
+(defun eat--post-prompt ()
+ "Put a mark in the marginal area and enter line mode."
+ (when eat-enable-shell-prompt-annotation
+ (let ((indicator
+ (if (zerop eat--shell-command-status)
+ (propertize
+ eat-shell-prompt-annotation-success-margin-indicator
+ 'face '(eat-shell-prompt-annotation-success default))
+ (propertize
+ eat-shell-prompt-annotation-failure-margin-indicator
+ 'face '(eat-shell-prompt-annotation-failure default)))))
+ ;; Update previous prompt's indicator using side-effect.
+ (when eat--shell-prompt-mark
+ (setf (cadr eat--shell-prompt-mark) indicator)
+ (setq eat--shell-prompt-mark nil))
+ ;; Show this prompt's indicator.
+ (when eat--shell-prompt-begin
+ (when (< eat--shell-prompt-begin (point))
+ ;; Save it, we'll use side-effect.
+ (setq eat--shell-prompt-mark
+ `((margin ,eat-shell-prompt-annotation-position)
+ ,indicator))
+ ;; Make overlay and put bookkeeping properties.
+ (let ((identifier (gensym "eat--prompt-mark-identifier-"))
+ (before-str
+ (propertize " " 'display eat--shell-prompt-mark))
+ (ov (make-overlay eat--shell-prompt-begin
+ (1+ eat--shell-prompt-begin))))
+ (overlay-put ov 'before-string before-str)
+ (overlay-put ov 'eat--shell-prompt-mark-id identifier)
+ (add-text-properties
+ eat--shell-prompt-begin (1+ eat--shell-prompt-begin)
+ (list 'eat--before-string before-str
+ 'eat--shell-prompt-mark-id identifier
+ 'eat--shell-prompt-mark-overlay ov))
+ (push ov eat--shell-prompt-mark-overlays))))))
+ (when eat--shell-prompt-begin
+ (when (< eat--shell-prompt-begin (point))
+ ;; Put a text property for `eat-narrow-to-shell-prompt'.
+ (put-text-property eat--shell-prompt-begin
+ (1+ eat--shell-prompt-begin)
+ 'eat--shell-prompt-begin t)
+ ;; Put a text property to allow shell prompt navigation.
+ (put-text-property (1- (point)) (point)
+ 'eat--shell-prompt-end t)))
+ (setq eat--shell-prompt-begin nil)
+ (when eat-enable-auto-line-mode
+ (eat--line-mode-enter-auto)))
+
+(defun eat--post-cont-prompt ()
+ "Enter line mode."
+ (when eat-enable-auto-line-mode
+ (eat--line-mode-enter-auto)))
+
+(defun eat--correct-shell-prompt-mark-overlays (buffer)
+ "Correct all overlays used to add mark before shell prompt.
+
+BUFFER is the terminal buffer."
+ (when (and (buffer-live-p buffer)
+ (buffer-local-value 'eat-terminal buffer)
+ eat-enable-shell-prompt-annotation)
+ (with-current-buffer buffer
+ (while-no-input
+ ;; Delete all outdated overlays.
+ (dolist (ov eat--shell-prompt-mark-overlays)
+ (unless (and (<= (point-min) (overlay-start ov)
+ (1- (point-max)))
+ (eq (overlay-get ov 'eat--shell-prompt-mark-id)
+ (get-text-property
+ (overlay-start ov)
+ 'eat--shell-prompt-mark-id)))
+ (delete-overlay ov)
+ (setq eat--shell-prompt-mark-overlays
+ (delq ov eat--shell-prompt-mark-overlays))))
+ (save-excursion
+ ;; Recreate overlays if needed.
+ (goto-char (max (eat-term-beginning eat-terminal)
+ (point-min)))
+ (while (< (point) (min (eat-term-end eat-terminal)
+ (point-max)))
+ (when (get-text-property
+ (point) 'eat--shell-prompt-mark-id)
+ (let ((ov (get-text-property
+ (point) 'eat--shell-prompt-mark-overlay)))
+ (unless (and
+ ov (overlay-buffer ov)
+ (eq (overlay-get
+ ov 'eat--shell-prompt-mark-id)
+ (get-text-property
+ (point) 'eat--shell-prompt-mark-id)))
+ ;; Recreate.
+ (when ov
+ (delete-overlay ov)
+ (setq eat--shell-prompt-mark-overlays
+ (delq ov eat--shell-prompt-mark-overlays)))
+ (setq ov (make-overlay (point) (1+ (point))))
+ (overlay-put ov 'before-string
+ (get-text-property
+ (point) 'eat--before-string))
+ (overlay-put ov 'eat--shell-prompt-mark-id
+ (get-text-property
+ (point) 'eat--shell-prompt-mark-id))
+ (push ov eat--shell-prompt-mark-overlays))))
+ (goto-char (or (next-single-property-change
+ (point) 'eat--shell-prompt-mark-id nil
+ (min (eat-term-end eat-terminal)
+ (point-max)))
+ (min (eat-term-end eat-terminal)
+ (point-max))))))))))
+
+(defun eat--set-cmd (cmd)
+ "Add CMD to `shell-command-history'."
+ (when-let* ((eat-enable-shell-command-history)
+ (command (ignore-errors (decode-coding-string
+ (base64-decode-string cmd)
+ locale-coding-system))))
+ (add-to-history 'shell-command-history command)))
+
+(defun eat--pre-cmd ()
+ "Update shell prompt mark to indicate command is running."
+ ;; FIXME: It's a crime to touch processes in this section.
+ (when (eq eat-query-before-killing-running-terminal 'auto)
+ (set-process-query-on-exit-flag
+ (eat-term-parameter eat-terminal 'eat--process) t))
+ (when (and eat-enable-shell-prompt-annotation
+ eat--shell-prompt-mark)
+ (setf (cadr eat--shell-prompt-mark)
+ (propertize
+ eat-shell-prompt-annotation-running-margin-indicator
+ 'face '(eat-shell-prompt-annotation-running default))))
+ (when eat-enable-auto-line-mode
+ (eat--line-mode-exit-auto)))
+
+(defun eat--set-cmd-status (code)
+ "Set CODE as the current shell command's exit status."
+ (when eat-enable-shell-prompt-annotation
+ ;; We'll update the mark later when the prompt appears.
+ (setq eat--shell-command-status code)))
+
+(defun eat--before-new-prompt ()
+ "Allow entering line mode."
+ (setq eat--inhibit-auto-line-mode nil))
+
+(defun eat--get-shell-history (hist format)
+ "Get shell history from HIST in format FORMAT."
+ (pcase hist
+ (`(,host . ,file)
+ (setq host (ignore-errors
+ (decode-coding-string (base64-decode-string host)
+ locale-coding-system)))
+ (setq file (ignore-errors
+ (decode-coding-string (base64-decode-string file)
+ locale-coding-system)))
+ (if (and host file
+ (string= host (system-name))
+ (file-readable-p file))
+ (let ((str nil))
+ (eat-term-send-string eat-terminal "\e]51;e;I;0\e\\")
+ (with-temp-buffer
+ (insert-file-contents file)
+ (setq str (buffer-string)))
+ (eat--line-populate-input-ring str format))
+ (eat-term-send-string
+ eat-terminal
+ (format "\e]51;e;I;%s\e\\" eat-line-input-ring-size))))
+ ((pred stringp)
+ (eat--line-populate-input-ring
+ (ignore-errors
+ (decode-coding-string (base64-decode-string hist)
+ locale-coding-system))
+ format))))
+
+(defun eat--handle-message (name &rest args)
+ "Handle message with handler name NAME and ARGS."
+ (when-let* ((name (ignore-errors (decode-coding-string
+ (base64-decode-string name)
+ locale-coding-system)))
+ (handler (assoc name eat-message-handler-alist)))
+ (save-restriction
+ (widen)
+ (save-excursion
+ (apply (cdr handler)
+ (mapcar (lambda (arg)
+ (ignore-errors (decode-coding-string
+ (base64-decode-string arg)
+ locale-coding-system)))
+ args))))))
+
+(defun eat--handle-uic (_ cmd)
+ "Handle UI Command sequence CMD."
+ (pcase cmd
+ ;; In XTerm, OSC 51 is reserved for Emacs shell. I have no idea
+ ;; why, but Vterm uses this OSC to set the current directory and
+ ;; remotely execute Emacs Lisp code. Vterm uses the characters
+ ;; 'A' and 'E' as the first character of second parameter of this
+ ;; OSC. We use 'e' as the second parameter, followed by one or
+ ;; more parameters.
+ ;; UIC e ; A ; <t> ; <s> ST.
+ ((rx string-start "e;A;"
+ (let host (zero-or-more (not (any ?\;))))
+ ?\; (let path (zero-or-more anything))
+ string-end)
+ (eat--set-cwd-uic host path))
+ ;; UIC e ; B ST.
+ ("e;B"
+ (eat--pre-prompt))
+ ;; UIC e ; C ST.
+ ("e;C"
+ (eat--post-prompt))
+ ;; UIC e ; D ST.
+ ("e;D"
+ ;; Start of continuation prompt.
+ ;; Defined but unused.
+ )
+ ;; UIC e ; E ST.
+ ("e;E"
+ (eat--post-cont-prompt))
+ ;; UIC e ; F ; <t> ST.
+ ((rx string-start "e;F;"
+ (let cmd (zero-or-more anything))
+ string-end)
+ (eat--set-cmd cmd))
+ ;; UIC e ; G ST
+ ("e;G"
+ (eat--pre-cmd))
+ ;; UIC e ; H ; <n> ST.
+ ((rx string-start "e;H;"
+ (let status (one-or-more digit))
+ string-end)
+ (eat--set-cmd-status (string-to-number status)))
+ ;; UIC e ; I ; 0 ; <t> ; <t> ; <t> ST.
+ ((rx string-start "e;I;0;"
+ (let format (zero-or-more (not (any ?\;))))
+ ?\; (let host (zero-or-more (not (any ?\;))))
+ ?\; (let path (zero-or-more anything))
+ string-end)
+ (eat--get-shell-history (cons host path) format))
+ ;; UIC e ; I ; 1 ; <t> ; <t> ST.
+ ((rx string-start "e;I;1;"
+ (let format (zero-or-more (not (any ?\;))))
+ ?\; (let hist (zero-or-more anything))
+ string-end)
+ (eat--get-shell-history hist format))
+ ;; UIC e ; J ST.
+ ("e;J"
+ (eat--before-new-prompt))
+ ;; UIC e ; M ; ... ST.
+ ((rx string-start "e;M;"
+ (let msg (zero-or-more anything))
+ string-end)
+ (apply #'eat--handle-message (string-split msg ";")))))
+
+(defun eat-previous-shell-prompt (&optional arg)
+ "Go to the previous shell prompt.
+
+When numeric prefix argument, ARG, is given, go to ARGth previous
+shell prompt."
+ (interactive "p")
+ (dotimes (_ (or arg 1))
+ (let ((previous (previous-single-property-change
+ (point) 'eat--shell-prompt-end)))
+ (goto-char (or previous (point-min)))
+ (when (get-text-property (point) 'eat--shell-prompt-end)
+ (setq previous (previous-single-property-change
+ (point) 'eat--shell-prompt-end))
+ (goto-char (or previous (point-min))))
+ (unless previous
+ (user-error "No previous prompt")))))
+
+(defun eat-next-shell-prompt (&optional arg)
+ "Go to the next shell prompt.
+
+When numeric prefix argument, ARG, is given, go to ARGth next shell
+prompt."
+ (interactive "p")
+ (dotimes (_ (or arg 1))
+ (let ((next (next-single-property-change
+ (point) 'eat--shell-prompt-end)))
+ (goto-char (or next (point-max)))
+ (when (get-text-property (point) 'eat--shell-prompt-end)
+ (goto-char (or (next-single-property-change
+ (point) 'eat--shell-prompt-end)
+ (point-max))))
+ (unless next
+ (user-error "No next prompt")))))
+
+(defun eat-narrow-to-shell-prompt ()
+ "Narrow buffer to the shell prompt and following output at point."
+ (interactive)
+ (widen)
+ (narrow-to-region
+ (save-excursion
+ (while (not (or (bobp) (get-text-property
+ (point) 'eat--shell-prompt-begin)))
+ (goto-char (or (previous-single-property-change
+ (point) 'eat--shell-prompt-begin)
+ (point-min))))
+ (point))
+ (save-excursion
+ (when (and (not (eobp))
+ (get-text-property (point) 'eat--shell-prompt-begin))
+ (goto-char (or (next-single-property-change
+ (point) 'eat--shell-prompt-begin)
+ (point-max))))
+ (while (not (or (eobp) (get-text-property
+ (point) 'eat--shell-prompt-begin)))
+ (goto-char (or (next-single-property-change
+ (point) 'eat--shell-prompt-begin)
+ (point-max))))
+ (point))))
+
+\f
+;;;;; Input.
+
+(defvar eat--mouse-grabbing-type nil
+ "Current mouse grabbing type/mode.")
+
+(defvar eat--mouse-pressed-buttons nil
+ "Mouse buttons currently pressed.")
+
+(defvar eat--mouse-last-position nil
+ "Last position of mouse, nil when not dragging.")
+
+(defvar eat--mouse-drag-transient-map-exit nil
+ "Function to exit mouse dragging transient map.")
+
+(defun eat-self-input (n &optional e)
+ "Send E as input N times.
+
+N defaults to 1 and E defaults to `last-command-event' and should be a
+event."
+ (interactive
+ (list (prefix-numeric-value current-prefix-arg)
+ (if (and (> (length (this-command-keys)) 1)
+ (eq (aref (this-command-keys)
+ (- (length (this-command-keys)) 2))
+ meta-prefix-char))
+ ;; HACK: Capture meta modifier (ESC prefix) in terminal.
+ (cond
+ ((eq last-command-event meta-prefix-char)
+ last-command-event)
+ ((characterp last-command-event)
+ (aref
+ (kbd (format "M-%c" last-command-event))
+ 0))
+ ((symbolp last-command-event)
+ (aref
+ (kbd (format "M-<%S>" last-command-event))
+ 0))
+ (t
+ last-command-event))
+ last-command-event)))
+ (when (memq (event-basic-type e)
+ '( mouse-1 mouse-2 mouse-3 mouse-4 mouse-5 mouse-6
+ mouse-7 mouse-8 mouse-9 mouse-10 mouse-11))
+ (select-window (posn-window (event-start e))))
+ (when eat-terminal
+ (unless (mouse-movement-p e)
+ (funcall eat--synchronize-scroll-function
+ (eat--synchronize-scroll-windows 'force-selected)))
+ (if (memq (event-basic-type e)
+ '( mouse-1 mouse-2 mouse-3 mouse-4 mouse-5 mouse-6
+ mouse-7 mouse-8 mouse-9 mouse-10 mouse-11
+ mouse-movement))
+ (let ((disp-begin-posn
+ (posn-at-point
+ (eat-term-display-beginning eat-terminal)))
+ (e (if (or (not eat--mouse-last-position)
+ (eq (posn-window
+ (if (memq 'drag (event-modifiers e))
+ (event-end e)
+ (event-start e)))
+ (posn-window eat--mouse-last-position)))
+ e
+ (pcase e
+ (`(,type ,_)
+ `(,type ,eat--mouse-last-position))
+ (`(,type ,start ,_)
+ `(,type ,start ,eat--mouse-last-position))
+ (ev ev)))))
+ (if (not (mouse-movement-p e))
+ (eat-term-input-event eat-terminal n e disp-begin-posn)
+ (if (not eat--mouse-pressed-buttons)
+ (when (eq eat--mouse-grabbing-type :all)
+ (eat-term-input-event eat-terminal n e
+ disp-begin-posn))
+ (when (memq eat--mouse-grabbing-type '(:all :drag))
+ (eat-term-input-event eat-terminal n e
+ disp-begin-posn))
+ (setq eat--mouse-last-position (event-start e))))
+ (when (memq (event-basic-type e) '(mouse-1 mouse-2 mouse-3))
+ (when (or (memq 'click (event-modifiers e))
+ (memq 'drag (event-modifiers e)))
+ (setq eat--mouse-pressed-buttons
+ (delq (event-basic-type e)
+ eat--mouse-pressed-buttons))
+ (unless eat--mouse-pressed-buttons
+ (setq eat--mouse-last-position nil)
+ (when eat--mouse-drag-transient-map-exit
+ (funcall eat--mouse-drag-transient-map-exit)
+ (setq eat--mouse-drag-transient-map-exit nil))))
+ (when (memq 'down (event-modifiers e))
+ (push (event-basic-type e) eat--mouse-pressed-buttons)
+ (setq eat--mouse-last-position (event-start e))
+ (unless eat--mouse-drag-transient-map-exit
+ (let ((old-track-mouse track-mouse)
+ (buffer (current-buffer)))
+ (setq track-mouse 'dragging)
+ (setq eat--mouse-drag-transient-map-exit
+ (set-transient-map
+ (let ((map (eat-term-make-keymap
+ #'eat-self-input
+ '(:mouse-modifier
+ :mouse-movement)
+ nil)))
+ ;; Some of the events will of course end up
+ ;; looked up with a mode-line, header-line
+ ;; or vertical-line prefix ...
+ (define-key map [mode-line] map)
+ (define-key map [header-line] map)
+ (define-key map [tab-line] map)
+ (define-key map [vertical-line] map)
+ ;; ... and some maybe even with a right- or
+ ;; bottom-divider prefix.
+ (define-key map [right-divider] map)
+ (define-key map [bottom-divider] map))
+ #'always
+ (lambda ()
+ (with-current-buffer buffer
+ (setq track-mouse
+ old-track-mouse))))))))))
+ (eat-term-input-event eat-terminal n e))))
+
+(defun eat-quoted-input ()
+ "Read a character and send it as INPUT."
+ (declare (interactive-only "Use `eat-self-input' instead."))
+ (interactive)
+ ;; HACK: Quick hack to allow inputting `C-g'. Any better way to do
+ ;; this?
+ (eat-self-input
+ 1 (let ((inhibit-quit t)
+ ;; Don't trigger `quit' exiting this `let'.
+ (quit-flag nil))
+ (read-event))))
+
+(defun eat-input-char (character count)
+ "Input CHARACTER, COUNT times.
+
+Interactively, ask for the character CHARACTER to input. The numeric prefix
+argument COUNT specifies how many times to insert CHARACTER."
+ (declare (interactive-only "Use `eat-self-input' instead."))
+ (interactive (list (read-char-by-name
+ "Insert character (Unicode name or hex): ")
+ (prefix-numeric-value current-prefix-arg)))
+ (eat-self-input count character))
+
+(defvar yank-transform-functions) ; In `simple'.
+
+(defun eat-yank (&optional arg)
+ "Same as `yank', but for Eat.
+
+ARG is passed to `yank', which see."
+ (interactive "*P")
+ (when eat-terminal
+ (funcall eat--synchronize-scroll-function
+ (eat--synchronize-scroll-windows 'force-selected))
+ (eat-term-send-string-as-yank
+ eat-terminal
+ (let ((yank-hook (bound-and-true-p yank-transform-functions)))
+ (with-temp-buffer
+ (setq-local yank-transform-functions yank-hook)
+ (yank arg)
+ (buffer-string))))))
+
+(defun eat-yank-from-kill-ring (string &optional arg)
+ "Same as `yank-from-kill-ring', but for Eat.
+
+STRING and ARG are passed to `yank-pop', which see."
+ (interactive
+ (progn
+ (unless (eval-when-compile (>= emacs-major-version 28))
+ (error "`eat-yank-from-kill-ring' requires at least Emacs 28"))
+ (list (read-from-kill-ring "Yank from kill-ring: ")
+ current-prefix-arg)))
+ (unless (eval-when-compile (>= emacs-major-version 28))
+ (error "`eat-yank-from-kill-ring' requires at least Emacs 28"))
+ (when eat-terminal
+ (funcall eat--synchronize-scroll-function
+ (eat--synchronize-scroll-windows 'force-selected))
+ (eat-term-send-string-as-yank
+ eat-terminal
+ (let ((yank-hook (bound-and-true-p yank-transform-functions)))
+ (with-temp-buffer
+ (setq-local yank-transform-functions yank-hook)
+ (yank-from-kill-ring string arg)
+ (buffer-string))))))
+
+(defun eat-mouse-yank-primary (&optional event)
+ "Send the primary selection to the terminal.
+
+EVENT is the mouse event."
+ (interactive "e")
+ (when select-active-regions
+ (let (select-active-regions)
+ (deactivate-mark)))
+ (unless (windowp (posn-window (event-start event)))
+ (error "Position not in text area of window"))
+ (select-window (posn-window (event-start event)))
+ (eat-term-send-string-as-yank
+ eat-terminal (gui-get-primary-selection)))
+
+(defun eat-mouse-yank-secondary (&optional event)
+ "Send the secondary selection to the terminal.
+
+EVENT is the mouse event."
+ (interactive "e")
+ (unless (windowp (posn-window (event-start event)))
+ (error "Position not in text area of window"))
+ (select-window (posn-window (event-start event)))
+ (let ((secondary (gui-get-selection 'SECONDARY)))
+ (if secondary
+ (eat-term-send-string-as-yank eat-terminal secondary)
+ (error "No secondary selection"))))
+
+(defun eat-xterm-paste (event)
+ "Handle paste operation EVENT from XTerm."
+ (interactive "e")
+ (unless (eq (car-safe event) 'xterm-paste)
+ (error "`eat-xterm-paste' must be bind to `xterm-paste' event"))
+ (let ((pasted-text (nth 1 event)))
+ (if (bound-and-true-p xterm-store-paste-on-kill-ring)
+ ;; Put the text onto the kill ring and then insert it into the
+ ;; buffer.
+ (let ((interprogram-paste-function (lambda () pasted-text)))
+ (eat-yank))
+ ;; Insert the text without putting it onto the kill ring.
+ (eat-term-send-string-as-yank eat-terminal pasted-text))))
+
+(defun eat-send-password ()
+ "Read password from minibuffer and send it to the terminal."
+ (declare (interactive-only t))
+ (interactive)
+ (unless eat-terminal
+ (user-error "Process not running"))
+ (eat-term-send-string eat-terminal (read-passwd "Password: "))
+ (eat-self-input 1 'return))
+
+;; When changing these keymaps, be sure to update the manual, README
+;; and commentary.
+(defvar eat-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [?\C-c ?\M-d] #'eat-char-mode)
+ (define-key map [?\C-c ?\C-j] #'eat-semi-char-mode)
+ (define-key map [?\C-c ?\C-l] #'eat-line-mode)
+ (define-key map [?\C-c ?\C-k] #'eat-kill-process)
+ (define-key map [?\C-c ?\C-p] #'eat-previous-shell-prompt)
+ (define-key map [?\C-c ?\C-n] #'eat-next-shell-prompt)
+ (define-key map [?\C-x ?n ?d] #'eat-narrow-to-shell-prompt)
+ (define-key map [xterm-paste] #'ignore)
+ map)
+ "Keymap for Eat mode.")
+
+(defun eat--prepare-semi-char-mode-map ()
+ "Prepare `eat-semi-char-mode-map'."
+ (let ((map (eat-term-make-keymap
+ #'eat-self-input '(:ascii :arrow :navigation)
+ `([?\C-c] [?\C-q] [?\C-y] [?\e ?y]
+ ,@eat-semi-char-non-bound-keys))))
+ (define-key map [?\C-q] #'eat-quoted-input)
+ (define-key map [?\C-y] #'eat-yank)
+ (define-key map [?\M-y] #'eat-yank-from-kill-ring)
+ (define-key map [?\C-c ?\C-c] #'eat-self-input)
+ (define-key map [?\C-c ?\C-e] #'eat-emacs-mode)
+ (define-key map [S-insert] #'eat-yank)
+ (define-key map [remap insert-char] #'eat-input-char)
+ (define-key map [remap mouse-yank-primary]
+ #'eat-mouse-yank-primary)
+ (define-key map [remap mouse-yank-secondary]
+ #'eat-mouse-yank-secondary)
+ (define-key map [xterm-paste] #'eat-xterm-paste)
+ map))
+
+(defvar eat-semi-char-mode-map (ignore-errors
+ (eat--prepare-semi-char-mode-map))
+ "Keymap for Eat semi-char mode.")
+
+(defun eat-update-semi-char-mode-map ()
+ "Update \"semi-char\" keybinding mode's keymap."
+ (setq eat-semi-char-mode-map (eat--prepare-semi-char-mode-map)))
+
+(defvar eat-char-mode-map
+ (let ((map (eat-term-make-keymap
+ #'eat-self-input '(:ascii :arrow :navigation :function)
+ '([?\e ?\C-m]))))
+ (define-key map [?\C-\M-m] #'eat-semi-char-mode)
+ (define-key map [xterm-paste] #'eat-xterm-paste)
+ map)
+ "Keymap for Eat char mode.")
+
+(defvar eat-line-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [?\C-c ?\C-e] #'eat-emacs-mode)
+ (define-key map [?\t] #'completion-at-point)
+ (define-key map [?\C-m] #'eat-line-send-input)
+ (define-key map [?\C-d] #'eat-line-delchar-or-eof)
+ (define-key map [?\C-c ?\C-c] #'eat-line-send-interrupt)
+ (define-key map [?\C-c ?\s] #'newline)
+ (define-key map [?\M-p] #'eat-line-previous-input)
+ (define-key map [?\M-n] #'eat-line-next-input)
+ (define-key map [C-up] #'eat-line-previous-input)
+ (define-key map [C-down] #'eat-line-next-input)
+ (define-key map [?\M-r]
+ #'eat-line-history-isearch-backward-regexp)
+ (define-key map [?\C-c ?\C-r] #'eat-line-find-input)
+ (define-key map [?\C-c ?\M-r]
+ #'eat-line-previous-matching-input-from-input)
+ (define-key map [?\C-c ?\M-s]
+ #'eat-line-next-matching-input-from-input)
+ map)
+ "Keymap for Eat line mode.")
+
+(defvar eat--mouse-click-mode-map
+ (eat-term-make-keymap #'eat-self-input '(:mouse-click) nil)
+ "Keymap for `eat--mouse-click-mode'.")
+
+(defvar eat--mouse-modifier-click-mode-map
+ (eat-term-make-keymap #'eat-self-input '(:mouse-modifier) nil)
+ "Keymap for `eat--mouse-modifier-click-mode'.")
+
+(defvar eat--mouse-movement-mode-map
+ (eat-term-make-keymap #'eat-self-input '(:mouse-movement) nil)
+ "Keymap for `eat--mouse-movement-mode'.")
+
+(define-minor-mode eat--semi-char-mode
+ "Minor mode for semi-char mode keymap."
+ :interactive nil
+ :keymap eat-semi-char-mode-map)
+
+(define-minor-mode eat--char-mode
+ "Minor mode for char mode keymap."
+ :interactive nil
+ :keymap eat-char-mode-map)
+
+(define-minor-mode eat--mouse-click-mode
+ "Minor mode for mouse click keymap."
+ :interactive nil)
+
+(define-minor-mode eat--mouse-modifier-click-mode
+ "Minor mode for mouse click with modifiers keymap."
+ :interactive nil)
+
+(define-minor-mode eat--mouse-movement-mode
+ "Minor mode for mouse movement keymap."
+ :interactive nil)
+
+(defun eat-emacs-mode ()
+ "Switch to Emacs keybindings mode."
+ (interactive)
+ (eat--line-mode-exit)
+ (eat--semi-char-mode -1)
+ (eat--char-mode -1)
+ (setq buffer-read-only t)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (force-mode-line-update))
+
+(defun eat-semi-char-mode ()
+ "Switch to semi-char mode."
+ (interactive)
+ (unless eat-terminal
+ (error "Process not running"))
+ (setq buffer-read-only nil)
+ (eat--line-mode-exit)
+ (eat--char-mode -1)
+ (eat--semi-char-mode +1)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (force-mode-line-update))
+
+(defun eat-char-mode ()
+ "Switch to char mode."
+ (interactive)
+ (unless eat-terminal
+ (error "Process not running"))
+ (setq buffer-read-only nil)
+ (eat--line-mode-exit)
+ (eat--semi-char-mode -1)
+ (eat--char-mode +1)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (force-mode-line-update))
+
+(defvar eat--eshell-semi-char-mode)
+(defvar eat--eshell-char-mode)
+
+(defun eat--grab-mouse (_ mode)
+ "Grab mouse.
+
+MODE should one of:
+
+ nil Disable mouse.
+ `:click' Pass `mouse-1', `mouse-2', and `mouse-3'
+ clicks.
+ `:modifier-click' Pass all mouse clicks, including control,
+ meta and shift modifiers.
+ `:drag' All of :modifier-click, plus dragging
+ (moving mouse while pressed) information.
+ `:all' Pass all mouse events, including movement.
+ Any other value Disable mouse."
+ (setq eat--mouse-grabbing-type mode)
+ (pcase (and eat-enable-mouse
+ (or eat--semi-char-mode
+ eat--char-mode
+ eat--eshell-semi-char-mode
+ eat--eshell-char-mode)
+ mode)
+ (:all
+ (setq track-mouse t)
+ (eat--mouse-click-mode -1)
+ (eat--mouse-modifier-click-mode +1)
+ (eat--mouse-movement-mode +1))
+ ((or :modifier-click :drag)
+ (setq track-mouse nil)
+ (eat--mouse-click-mode -1)
+ (eat--mouse-movement-mode -1)
+ (eat--mouse-modifier-click-mode +1))
+ (:click
+ (setq track-mouse nil)
+ (eat--mouse-modifier-click-mode -1)
+ (eat--mouse-movement-mode -1)
+ (eat--mouse-click-mode +1))
+ (_
+ (setq track-mouse nil)
+ (eat--mouse-click-mode -1)
+ (eat--mouse-modifier-click-mode -1)
+ (eat--mouse-movement-mode -1))))
+
+\f
+;;;;; Line Mode.
+
+(define-minor-mode eat--line-mode
+ "Minor mode for line mode."
+ :interactive nil
+ :keymap eat-line-mode-map
+ (if eat--line-mode
+ (let ((inhibit-read-only t))
+ (add-hook 'pre-command-hook #'eat--line-move-to-input nil t)
+ (add-text-properties (eat-term-beginning eat-terminal)
+ (eat-term-end eat-terminal)
+ '(front-sticky t rear-nonsticky t)))
+ (remove-hook 'pre-command-hook #'eat--line-move-to-input t)
+ (let ((inhibit-read-only t))
+ (when (/= (eat-term-beginning eat-terminal)
+ (eat-term-end eat-terminal))
+ (remove-text-properties
+ (eat-term-beginning eat-terminal)
+ (eat-term-end eat-terminal)
+ '(front-sticky nil rear-nonsticky nil))))))
+
+(defun eat-line-mode ()
+ "Switch to line mode."
+ (interactive)
+ (unless eat-terminal
+ (error "Process not running"))
+ (eat--line-mode +1)
+ (eat--semi-char-mode -1)
+ (eat--char-mode -1)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (setq buffer-read-only nil)
+ ;; Delete the undo list so that `undo' doesn't mess up with the
+ ;; terminal.
+ (setq buffer-undo-list nil)
+ ;; Don't let auto line mode exit line mode.
+ (setq eat--inhibit-auto-line-mode t))
+
+(defun eat--line-mode-exit ()
+ "Exit line mode, called only by interactive commands."
+ (when eat--line-mode
+ (when (/= (eat-term-end eat-terminal) (point-max))
+ (eat-line-send))
+ (eat--line-mode -1)
+ (setq buffer-undo-list nil)
+ (setq eat--inhibit-auto-line-mode t)
+ (setq eat--auto-line-mode-prev-mode nil)))
+
+(defun eat--line-move-to-input ()
+ "Move point to the input line."
+ (when (and eat-line-auto-move-to-input
+ (< (point) (eat-term-end eat-terminal))
+ (eq #'self-insert-command this-command))
+ (deactivate-mark)
+ (push-mark)
+ (goto-char (point-max))))
+
+(defun eat-line-send-default ()
+ "Send shell prompt input directly to the terminal."
+ (eat-term-send-string eat-terminal (buffer-string))
+ ;; If output arrives after sending the string, new output may get
+ ;; included in the narrowed region. So we narrow it again so that
+ ;; we don't get a `text-read-only' for trying to delete text in the
+ ;; terminal.
+ (narrow-to-region (eat-term-end eat-terminal) (point-max)))
+
+(defun eat-line-send ()
+ "Send shell prompt input to the terminal."
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (eat-term-end eat-terminal) (point-max))
+ (funcall eat-line-input-send-function)
+ (delete-region (point-min) (point-max))
+ (eat--line-reset-input-ring-vars)
+ (setq buffer-undo-list nil)))
+ (goto-char (eat-term-display-cursor eat-terminal)))
+
+(defvar eat--line-input-ring)
+
+(defun eat-line-send-input (&optional no-newline)
+ "Send shell prompt input to the terminal.
+
+If called without any prefix argument, or if NO-NEWLINE is nil, append
+a newline to the input before sending it."
+ (interactive "P")
+ (if (not (<= (eat-term-end eat-terminal) (point)))
+ (call-interactively #'newline)
+ (unless (= (eat-term-end eat-terminal) (point-max))
+ (unless eat--line-input-ring
+ (setq eat--line-input-ring
+ (make-ring eat-line-input-ring-size)))
+ (ring-insert eat--line-input-ring
+ (buffer-substring-no-properties
+ (eat-term-end eat-terminal) (point-max))))
+ (unless no-newline
+ (goto-char (point-max))
+ (insert "\n"))
+ (eat-line-send)))
+
+(defun eat-line-delchar-or-eof (arg)
+ "Delete character or send shell prompt input to the terminal.
+
+ARG is the prefix arg, passed to `delete-char' when deleting
+character."
+ (interactive "p")
+ (if (not (= (eat-term-end eat-terminal) (point-max)))
+ (delete-char arg)
+ (insert "\C-d")
+ (eat-line-send)))
+
+(defun eat-line-send-interrupt ()
+ "Clear the input and send `C-c' to the shell."
+ (interactive)
+ (delete-region (eat-term-end eat-terminal) (point-max))
+ (goto-char (point-max))
+ (insert "\C-c")
+ (eat-line-send))
+
+\f
+;;;;;; History.
+
+;; The following code in this page (or section) is adapted from
+;; Comint source.
+
+(defvar eat--line-input-ring nil
+ "Ring holding the history of inputs.")
+
+(defvar eat--line-input-ring-index nil
+ "Index of last matched history element.")
+
+(defvar eat--line-stored-incomplete-input nil
+ "Stored input for history cycling.")
+
+(defvar eat--line-matching-input-from-input-string ""
+ "Input previously used to match input history.")
+
+(defvar eat--saved-line-input-history-isearch 'not-saved
+ "Saved value of `eat-line-input-history-isearch'.")
+
+(defun eat--line-reset-input-ring-vars ()
+ "Reset variable after a new shell prompt."
+ (setq eat--line-input-ring-index nil)
+ (setq eat--line-stored-incomplete-input nil)
+ (setq eat--line-matching-input-from-input-string ""))
+
+(defun eat--line-populate-input-ring (hist format)
+ "Populate `eat--line-input-ring' from HIST in format FORMAT."
+ (setq eat--line-input-ring (make-ring eat-line-input-ring-size))
+ (pcase format
+ ("bash"
+ (dolist (item (string-split hist "\n" 'omit-nulls))
+ (when (/= (aref item 0) ?#)
+ (ring-insert eat--line-input-ring item))))
+ ("zsh"
+ (dolist (item (string-split hist "\n" 'omit-nulls))
+ (ring-insert eat--line-input-ring
+ (string-trim item (rx ": " (zero-or-more digit)
+ ?: (zero-or-more digit)
+ ?\;)))))))
+
+(defun eat-line-load-input-history-from-file (file format)
+ "Load input history from FILE.
+
+FORMAT is the format of FILE."
+ (interactive
+ (let ((file (read-file-name "History file: ")))
+ (list file (completing-read
+ "History file format: " '("bash" "zsh")
+ nil t (pcase (file-name-nondirectory file)
+ (".bash_history" "bash")
+ (".zsh_history" "zsh"))))))
+ (let ((str nil))
+ (with-temp-buffer
+ (insert-file-contents file)
+ (setq str (buffer-string)))
+ (eat--line-populate-input-ring str format)))
+
+(defun eat--line-ask-for-regexp-arg (prompt)
+ "Return list of regexp and prefix arg using PROMPT."
+ (let* (;; Don't clobber this.
+ (last-command last-command)
+ (regexp (read-from-minibuffer
+ prompt nil nil nil
+ 'minibuffer-history-search-history)))
+ ;; If the user didn't enter anything, nothing is added to m-h-s-h.
+ ;; Use the previous search regexp, if there is one.
+ (list (if (string-equal regexp "")
+ (or (car minibuffer-history-search-history)
+ regexp)
+ regexp)
+ (prefix-numeric-value current-prefix-arg))))
+
+(defun eat--line-search-arg (arg)
+ "Check point, and return ARG, or one if ARG is zero."
+ ;; First make sure there is a ring and that we are after the
+ ;; terminal region.
+ (cond ((< (point) (eat-term-end eat-terminal))
+ (user-error "Not at command line"))
+ ((or (null eat--line-input-ring)
+ (ring-empty-p eat--line-input-ring))
+ (user-error "Empty input ring"))
+ ((zerop arg)
+ ;; ARG zero resets search from beginning, and uses ARG 1.
+ (setq eat--line-input-ring-index nil)
+ 1)
+ (t
+ arg)))
+
+(defun eat-line-restore-input ()
+ "Restore unfinished input."
+ (interactive)
+ (when eat--line-input-ring-index
+ (delete-region (eat-term-end eat-terminal) (point-max))
+ (when (> (length eat--line-stored-incomplete-input) 0)
+ (insert eat--line-stored-incomplete-input)
+ (message "Input restored"))
+ (setq eat--line-input-ring-index nil)))
+
+(defun eat--line-search-start (arg)
+ "Index to start a directional search, ARG indicates the direction."
+ (if eat--line-input-ring-index
+ ;; If a search is running, offset by 1 in direction of ARG.
+ (mod (+ eat--line-input-ring-index (if (> arg 0) 1 -1))
+ (ring-length eat--line-input-ring))
+ ;; For a new search, start from end if ARG is negative, or from
+ ;; beginning otherwise.
+ (if (> arg 0)
+ 0
+ (1- (ring-length eat--line-input-ring)))))
+
+(defun eat--line-prev-input-string (arg)
+ "Return the string ARG places along the input ring.
+Moves relative to `eat--line-input-ring-index'."
+ (ring-ref eat--line-input-ring
+ (if eat--line-input-ring-index
+ (mod (+ arg eat--line-input-ring-index)
+ (ring-length eat--line-input-ring))
+ arg)))
+
+(defun eat-line-previous-input (arg)
+ "Cycle backwards through input history, saving input.
+
+Negative ARG means search forward instead."
+ (interactive "*p")
+ (if (and eat--line-input-ring-index
+ ;; Are we leaving the "end" of the ring?
+ (or (and (< arg 0) ; going down
+ (eq eat--line-input-ring-index 0))
+ (and (> arg 0) ; going up
+ (eq eat--line-input-ring-index
+ (1- (ring-length eat--line-input-ring)))))
+ eat--line-stored-incomplete-input)
+ (eat-line-restore-input)
+ (eat-line-previous-matching-input "." arg)))
+
+(defun eat-line-next-input (arg)
+ "Cycle forwards through input history, saving input.
+
+Negative ARG means search backward instead."
+ (interactive "*p")
+ (eat-line-previous-input (- arg)))
+
+(defun eat--line-prev-matching-input-str (regexp arg)
+ "Return the string matching REGEXP ARG places along the input ring.
+Moves relative to `eat--line-input-ring-index'."
+ (let* ((pos (eat--line-prev-matching-input-str-pos regexp arg)))
+ (if pos (ring-ref eat--line-input-ring pos))))
+
+(defun eat--line-prev-matching-input-str-pos
+ (regexp arg &optional start)
+ "Return the index matching REGEXP ARG places along the input ring.
+Moves relative to START, or `eat--line-input-ring-index'."
+ (when (or (not (ring-p eat--line-input-ring))
+ (ring-empty-p eat--line-input-ring))
+ (user-error "No history"))
+ (let* ((len (ring-length eat--line-input-ring))
+ (motion (if (> arg 0) 1 -1))
+ (n (mod (- (or start (eat--line-search-start arg)) motion)
+ len))
+ (tried-each-ring-item nil)
+ (prev nil))
+ ;; Do the whole search as many times as the argument says.
+ (while (and (/= arg 0) (not tried-each-ring-item))
+ ;; Step once.
+ (setq prev n)
+ (setq n (mod (+ n motion) len))
+ ;; If we haven't reached a match, step some more.
+ (while (and (< n len) (not tried-each-ring-item)
+ (not (string-match regexp
+ (ring-ref
+ eat--line-input-ring n))))
+ (setq n (mod (+ n motion) len))
+ ;; If we have gone all the way around in this search.
+ (setq tried-each-ring-item (= n prev)))
+ (setq arg (if (> arg 0) (1- arg) (1+ arg))))
+ ;; Now that we know which ring element to use, if we found it,
+ ;; return that.
+ (when (string-match regexp (ring-ref eat--line-input-ring n))
+ n)))
+
+(defun eat-line-previous-matching-input (regexp n &optional restore)
+ "Search backwards through input history for match for REGEXP.
+
+\(Previous history elements are earlier commands.)
+With prefix argument N, search for Nth previous match.
+If N is negative, find the next or Nth next match.
+
+If RESTORE is non-nil, restore input in case of wrap."
+ (interactive (eat--line-ask-for-regexp-arg
+ "Previous input matching (regexp): "))
+ (setq n (eat--line-search-arg n))
+ (let ((pos (eat--line-prev-matching-input-str-pos regexp n)))
+ ;; Has a match been found?
+ (if (null pos)
+ (user-error "Not found")
+ (if (and eat--line-input-ring-index
+ restore
+ (or (and (< n 0)
+ (< eat--line-input-ring-index pos))
+ (and (> n 0)
+ (> eat--line-input-ring-index pos))))
+ ;; We have a wrap; restore contents.
+ (eat-line-restore-input)
+ ;; If leaving the edit line, save partial input.
+ (if (null eat--line-input-ring-index) ;not yet on ring
+ (setq eat--line-stored-incomplete-input
+ (buffer-substring-no-properties
+ (eat-term-end eat-terminal) (point-max))))
+ (setq eat--line-input-ring-index pos)
+ (unless isearch-mode
+ (let ((message-log-max nil)) ; Do not write to *Messages*.
+ (message "History item: %d" (1+ pos))))
+ (delete-region (eat-term-end eat-terminal) (point-max))
+ (insert (ring-ref eat--line-input-ring pos))))))
+
+(defun eat-line-next-matching-input (regexp n)
+ "Search forwards through input history for match for REGEXP.
+\(Later history elements are more recent commands.)
+With prefix argument N, search for Nth following match.
+If N is negative, find the previous or Nth previous match."
+ (interactive (eat--line-ask-for-regexp-arg
+ "Next input matching (regexp): "))
+ (eat-line-previous-matching-input regexp (- n)))
+
+(defun eat-line-previous-matching-input-from-input (n)
+ "Search backwards through input history for match for current input.
+\(Previous history elements are earlier commands.)
+With prefix argument N, search for Nth previous match.
+If N is negative, search forwards for the -Nth following match."
+ (interactive "p")
+ (let ((opoint (point)))
+ (unless (memq last-command
+ '(eat-line-previous-matching-input-from-input
+ eat-line-next-matching-input-from-input))
+ ;; Starting a new search
+ (setq eat--line-matching-input-from-input-string
+ (buffer-substring (eat-term-end eat-terminal)
+ (point-max)))
+ (setq eat--line-input-ring-index nil))
+ (eat-line-previous-matching-input
+ (concat "^" (regexp-quote
+ eat--line-matching-input-from-input-string))
+ n t)
+ (when (eq eat-line-move-point-for-matching-input 'after-input)
+ (goto-char opoint))))
+
+(defun eat-line-next-matching-input-from-input (n)
+ "Search forwards through input history for match for current input.
+\(Following history elements are more recent commands.)
+With prefix argument N, search for Nth following match.
+If N is negative, search backwards for the -Nth previous match."
+ (interactive "p")
+ (eat-line-previous-matching-input-from-input (- n)))
+
+(defun eat-line-find-input ()
+ "Find and insert input history using minibuffer."
+ (declare (interactive-only t))
+ (interactive)
+ (when (or (not (ring-p eat--line-input-ring))
+ (ring-empty-p eat--line-input-ring))
+ (user-error "No history"))
+ (let ((str (completing-read
+ "Input: "
+ (seq-uniq (ring-elements eat--line-input-ring)) nil
+ nil (buffer-substring (eat-term-end eat-terminal)
+ (point-max))))
+ (i 0)
+ (pos nil))
+ (while (and (< i (ring-length eat--line-input-ring)) (not pos))
+ (when (equal (ring-ref eat--line-input-ring i) str)
+ (setq pos i))
+ (cl-incf i))
+ (when pos
+ (setq eat--line-input-ring-index pos))
+ (delete-region (eat-term-end eat-terminal) (point-max))
+ (insert str)))
+
+(defun eat-line-history-isearch-backward ()
+ "Search for a string backward in input history using Isearch."
+ (interactive)
+ (setq eat--saved-line-input-history-isearch
+ eat-line-input-history-isearch)
+ (setq eat-line-input-history-isearch t)
+ (isearch-backward nil t))
+
+(defun eat-line-history-isearch-backward-regexp ()
+ "Search for a regular expression backward in input history using Isearch."
+ (interactive)
+ (setq eat--saved-line-input-history-isearch
+ eat-line-input-history-isearch)
+ (setq eat-line-input-history-isearch t)
+ (isearch-backward-regexp nil t))
+
+(defun eat--line-history-isearch-setup ()
+ "Set up Eat buffer for using Isearch to search the input history."
+ (when (or (eq eat-line-input-history-isearch t)
+ (and (eq eat-line-input-history-isearch 'dwim)
+ (>= (point) (eat-term-end eat-terminal))))
+ (setq isearch-message-prefix-add "history ")
+ (setq isearch-search-fun-function
+ #'eat--line-history-isearch-search)
+ (setq isearch-wrap-function #'eat--line-history-isearch-wrap)
+ (setq isearch-push-state-function
+ #'eat--line-history-isearch-push-state)
+ (make-local-variable 'isearch-lazy-count)
+ (setq isearch-lazy-count nil)
+ (add-hook 'isearch-mode-end-hook
+ 'eat--line-history-isearch-end nil t)))
+
+(defun eat--line-history-isearch-end ()
+ "Clean up after terminating Isearch."
+ (setq isearch-message-prefix-add nil)
+ (setq isearch-search-fun-function 'isearch-search-fun-default)
+ (setq isearch-wrap-function nil)
+ (setq isearch-push-state-function nil)
+ ;; Force isearch to not change mark.
+ (setq isearch-opoint (point))
+ (kill-local-variable 'isearch-lazy-count)
+ (remove-hook 'isearch-mode-end-hook
+ 'eat--line-history-isearch-end t)
+ (unless (or isearch-suspended
+ (eq eat--saved-line-input-history-isearch 'not-saved))
+ (setq eat-line-input-history-isearch
+ eat--saved-line-input-history-isearch)
+ (setq eat--saved-line-input-history-isearch 'not-saved)))
+
+(defun eat--line-goto-input (pos)
+ "Put input history item of the absolute history position POS."
+ ;; If leaving the edit line, save partial unfinished input.
+ (when (null eat--line-input-ring-index)
+ (setq eat--line-stored-incomplete-input
+ (buffer-substring-no-properties
+ (eat-term-end eat-terminal) (point-max))))
+ (setq eat--line-input-ring-index pos)
+ (delete-region (eat-term-end eat-terminal) (point-max))
+ (if (and pos (not (ring-empty-p eat--line-input-ring)))
+ (insert (ring-ref eat--line-input-ring pos))
+ ;; Restore partial unfinished input.
+ (when (> (length eat--line-stored-incomplete-input) 0)
+ (insert eat--line-stored-incomplete-input))))
+
+(defun eat--line-history-isearch-search ()
+ "Return the proper search function, for Isearch in input history."
+ (lambda (string bound noerror)
+ (let ((search-fun (isearch-search-fun-default))
+ found)
+ ;; Avoid lazy-highlighting matches in the input line and in the
+ ;; output when searching forward. Lazy-highlight calls this
+ ;; lambda with the bound arg, so skip the prompt and the output.
+ (when (and bound isearch-forward
+ (< (point) (eat-term-end eat-terminal)))
+ (goto-char (eat-term-end eat-terminal)))
+ (or
+ ;; 1. First try searching in the initial input line
+ (funcall search-fun string (if isearch-forward
+ bound
+ (eat-term-end eat-terminal))
+ noerror)
+ ;; 2. If the above search fails, start putting next/prev
+ ;; history elements in the input line successively, and search
+ ;; the string in them. Do this only when bound is nil
+ ;; (i.e. not while lazy-highlighting search strings in the
+ ;; current input line).
+ (unless bound
+ (condition-case nil
+ (progn
+ (while (not found)
+ (cond
+ (isearch-forward
+ ;; Signal an error here explicitly, because
+ ;; `eat-line-next-input' doesn't signal an
+ ;; error.
+ (when (null eat--line-input-ring-index)
+ (error "End of history; no next item"))
+ (eat-line-next-input 1)
+ (goto-char (eat-term-end eat-terminal)))
+ (t
+ ;; Signal an error here explicitly, because
+ ;; `eat-line-previous-input' doesn't signal an
+ ;; error.
+ (when (eq eat--line-input-ring-index
+ (1- (ring-length eat--line-input-ring)))
+ (error
+ "Beginning of history; no preceding item"))
+ (eat-line-previous-input 1)
+ (goto-char (point-max))))
+ (setq isearch-barrier (point))
+ (setq isearch-opoint (point))
+ ;; After putting the next/prev history element,
+ ;; search the string in them again, until
+ ;; `eat-line-next-input' or `eat-line-previous-input'
+ ;; raises an error at the beginning/end of history.
+ (setq found
+ (funcall search-fun string
+ (unless isearch-forward
+ ;; For backward search, don't search
+ ;; in the terminal region
+ (eat-term-end eat-terminal))
+ noerror)))
+ ;; Return point of the new search result
+ (point))
+ ;; Return nil on the error "no next/preceding item"
+ (error nil)))))))
+
+(defun eat--line-history-isearch-wrap ()
+ "Wrap the input history search when search fails.
+
+Move point to the first history element for a forward search,
+or to the last history element for a backward search."
+ ;; When `eat--line-history-isearch-search' fails on reaching the
+ ;; beginning/end of the history, wrap the search to the first/last
+ ;; input history element.
+ (if isearch-forward
+ (eat--line-goto-input (1- (ring-length eat--line-input-ring)))
+ (eat--line-goto-input nil))
+ (goto-char (if isearch-forward
+ (eat-term-end eat-terminal)
+ (point-max))))
+
+(defun eat--line-history-isearch-push-state ()
+ "Save a function restoring the state of input history search.
+
+Save `eat--line-input-ring-index' to the additional state parameter
+in the search status stack."
+ (let ((index eat--line-input-ring-index))
+ (lambda (cmd)
+ (eat--line-history-isearch-pop-state cmd index))))
+
+(defun eat--line-history-isearch-pop-state (_cmd hist-pos)
+ "Restore the input history search state.
+Go to the history element by the absolute history position HIST-POS."
+ (eat--line-goto-input hist-pos))
+
+\f
+;;;;; Major Mode.
+
+(defun eat--synchronize-scroll-windows (&optional force-selected)
+ "Return the list of windows whose scrolling should be synchronized.
+
+When FORCE-SELECTED is non-nil, always include `buffer' and the
+selected window in the list if the window is showing the current
+buffer."
+ `(,@(and (or force-selected
+ eat--char-mode
+ (= (eat-term-display-cursor eat-terminal) (point)))
+ '(buffer))
+ ,@(seq-filter
+ (lambda (window)
+ (or (and force-selected (eq window (selected-window)))
+ (= (eat-term-display-cursor eat-terminal)
+ (window-point window))))
+ (get-buffer-window-list))))
+
+(defun eat--synchronize-scroll (windows)
+ "Synchronize scrolling and point between terminal and WINDOWS.
+
+WINDOWS is a list of windows. WINDOWS may also contain the special
+symbol `buffer', in which case the point of current buffer is set."
+ (dolist (window windows)
+ (if (eq window 'buffer)
+ (goto-char (eat-term-display-cursor eat-terminal))
+ (with-selected-window window
+ (set-window-point nil (eat-term-display-cursor eat-terminal))
+ (recenter
+ (- (how-many "\n" (eat-term-display-beginning eat-terminal)
+ (eat-term-display-cursor eat-terminal))
+ (cdr (eat-term-size eat-terminal))
+ (max 0 (- (floor (window-screen-lines))
+ (cdr (eat-term-size eat-terminal))))))))))
+
+(defun eat--setup-glyphless-chars ()
+ "Setup the display of glyphless characters."
+ (setq-local glyphless-char-display
+ (copy-sequence (default-value 'glyphless-char-display)))
+ (set-char-table-extra-slot
+ glyphless-char-display 0
+ (if (display-graphic-p) 'empty-box 'thin-space)))
+
+(defun eat--filter-buffer-substring (begin end &optional delete)
+ "Filter buffer substring from BEGIN to END and return that.
+
+When DELETE is given and non-nil, delete the text between BEGIN and
+END if it's safe to do so."
+ (let ((str (buffer-substring begin end)))
+ (remove-text-properties 0 (length str)
+ '( read-only nil
+ rear-nonsticky nil
+ front-sticky nil
+ field nil
+ eat--before-string nil
+ eat--shell-prompt-mark-id nil
+ eat--shell-prompt-mark-overlay nil
+ eat--shell-prompt-begin nil
+ eat--shell-prompt-end nil)
+ str)
+ (setq str (eat-term-filter-string str))
+ (when (and delete
+ (or (not eat-terminal)
+ (and (<= (eat-term-end eat-terminal) begin)
+ (<= (eat-term-end eat-terminal) end))
+ (and (<= begin (eat-term-beginning eat-terminal))
+ (<= end (eat-term-beginning eat-terminal)))))
+ (delete-region begin end))
+ str))
+
+(define-derived-mode eat-mode fundamental-mode "Eat"
+ "Major mode for Eat."
+ :group 'eat-ui
+ (mapc #'make-local-variable
+ '(buffer-read-only
+ buffer-undo-list
+ filter-buffer-substring-function
+ mode-line-process
+ mode-line-buffer-identification
+ glyphless-char-display
+ cursor-type
+ track-mouse
+ scroll-margin
+ hscroll-margin
+ eat-terminal
+ eat--synchronize-scroll-function
+ eat--mouse-grabbing-type
+ eat--shell-command-status
+ eat--shell-prompt-begin
+ eat--shell-prompt-mark
+ eat--shell-prompt-mark-overlays
+ eat--inhibit-auto-line-mode
+ eat--auto-line-mode-prev-mode
+ eat--line-input-ring
+ eat--line-input-ring-index
+ eat--line-stored-incomplete-input
+ eat--line-matching-input-from-input-string
+ isearch-search-fun-function
+ isearch-wrap-function
+ isearch-push-state-function
+ eat--pending-output-chunks
+ eat--output-queue-first-chunk-time
+ eat--process-output-queue-timer
+ eat--shell-prompt-annotation-correction-timer))
+ ;; This is intended; input methods don't work on read-only buffers.
+ (setq buffer-read-only nil)
+ (setq scroll-margin 0)
+ (setq hscroll-margin 0)
+ (setq eat--synchronize-scroll-function #'eat--synchronize-scroll)
+ (setq filter-buffer-substring-function
+ #'eat--filter-buffer-substring)
+ (setq bidi-paragraph-direction 'left-to-right)
+ (setq eat--mouse-grabbing-type nil)
+ (add-hook 'isearch-mode-hook 'eat--line-history-isearch-setup nil t)
+ (setq mode-line-process
+ '(""
+ (:eval
+ (when eat-terminal
+ (cond
+ (eat--semi-char-mode
+ '("["
+ (:propertize
+ "semi-char"
+ help-echo "mouse-1: Switch to char mode, \
+mouse-2: Switch to line mode, mouse-3: Switch to emacs mode"
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-char-mode)
+ (down-mouse-2 . eat-line-mode)
+ (down-mouse-3 . eat-emacs-mode)))))
+ "]"))
+ (eat--char-mode
+ '("["
+ (:propertize
+ "char"
+ help-echo "mouse-1: Switch to semi-char mode, \
+mouse-2: Switch to line mode, mouse-3: Switch to emacs mode"
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-semi-char-mode)
+ (down-mouse-2 . eat-line-mode)
+ (down-mouse-3 . eat-emacs-mode)))))
+ "]"))
+ (eat--line-mode
+ '("["
+ (:propertize
+ "line"
+ help-echo "mouse-1: Switch to semi char mode, \
+mouse-2: Switch to emacs mode, mouse-3: Switch to char mode"
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-semi-char-mode)
+ (down-mouse-2 . eat-emacs-mode)
+ (down-mouse-3 . eat-char-mode)))))
+ "]"))
+ (t
+ '("["
+ (:propertize
+ "emacs"
+ help-echo "mouse-1: Switch to semi char mode, \
+mouse-3: Switch to char mode"
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-semi-char-mode)
+ (down-mouse-2 . eat-line-mode)
+ (down-mouse-3 . eat-char-mode)))))
+ "]")))))
+ ":%s"))
+ (setq mode-line-buffer-identification
+ `(12 (""
+ ,(nconc
+ (propertized-buffer-identification "%b")
+ '(" "
+ (:propertize
+ (:eval
+ (when-let* ((eat-terminal)
+ (title (eat-term-title eat-terminal))
+ ((not (string-empty-p title))))
+ (format "(%s)" (string-replace "%" "%%"
+ title))))
+ help-echo "Title"))))))
+ (eat-emacs-mode)
+ ;; Make sure glyphless character don't display a huge box glyph,
+ ;; that would break the display.
+ (eat--setup-glyphless-chars)
+ ;; Setup completion for line mode.
+ (shell-completion-vars)
+ (when eat-enable-blinking-text
+ (eat-blink-mode +1))
+ (when eat-enable-shell-prompt-annotation
+ (let ((margin-width
+ (max
+ (string-width
+ eat-shell-prompt-annotation-running-margin-indicator)
+ (string-width
+ eat-shell-prompt-annotation-success-margin-indicator)
+ (string-width
+ eat-shell-prompt-annotation-failure-margin-indicator))))
+ (pcase-exhaustive eat-shell-prompt-annotation-position
+ ('left-margin
+ (setq left-margin-width margin-width))
+ ('right-margin
+ (setq right-margin-width margin-width))))
+ ;; Make sure the marginal area is resized.
+ (dolist (win (get-buffer-window-list))
+ (set-window-buffer win (current-buffer)))))
+
+\f
+;;;;; Process Handling.
+
+(defvar eat--pending-output-chunks nil
+ "The list of pending output chunks.
+
+The output chunks are pushed, so last output appears first.")
+
+(defvar eat--output-queue-first-chunk-time nil
+ "Time when the first chunk in the current output queue was pushed.")
+
+(defvar eat--process-output-queue-timer nil
+ "Timer to process output queue.")
+
+(defvar eat--shell-prompt-annotation-correction-timer nil
+ "Timer to correct shell prompt annotations.")
+
+(defun eat-kill-process ()
+ "Kill Eat process in current buffer."
+ (interactive)
+ (when-let* ((eat-terminal)
+ (proc (eat-term-parameter eat-terminal 'eat--process)))
+ (delete-process proc)))
+
+(defun eat--send-string (process string)
+ "Send to PROCESS the contents of STRING as input.
+
+This is equivalent to `process-send-string', except that long input
+strings are broken up into chunks of size `eat-input-chunk-size'.
+Processes are given a chance to output between chunks. This can help
+prevent processes from hanging when you send them long inputs on some
+OS's."
+ (let ((i 0)
+ (j eat-input-chunk-size)
+ (l (length string)))
+ (while (< i l)
+ (process-send-string process (substring string i (min j l)))
+ (accept-process-output)
+ (cl-incf i eat-input-chunk-size)
+ (cl-incf j eat-input-chunk-size))))
+
+(defun eat--send-input (_ input)
+ "Send INPUT to subprocess."
+ (when-let* ((eat-terminal)
+ (proc (eat-term-parameter eat-terminal 'eat--process)))
+ (eat--send-string proc input)))
+
+(defun eat--process-output-queue (buffer)
+ "Process the output queue on BUFFER."
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (let ((inhibit-quit t) ; Don't disturb!
+ (sync-windows (eat--synchronize-scroll-windows))
+ (eat--auto-line-mode-pending-toggles nil))
+ (save-restriction
+ (widen)
+ (let ((inhibit-read-only t)
+ (inhibit-modification-hooks t)
+ ;; Don't let `undo' mess up with the terminal.
+ (buffer-undo-list t))
+ (when eat--process-output-queue-timer
+ (cancel-timer eat--process-output-queue-timer))
+ (setq eat--output-queue-first-chunk-time nil)
+ (while eat--pending-output-chunks
+ (let ((queue eat--pending-output-chunks)
+ (eat--output-queue-first-chunk-time t))
+ (setq eat--pending-output-chunks nil)
+ (dolist (output (nreverse queue))
+ (eat-term-process-output eat-terminal output))))
+ (eat-term-redisplay eat-terminal)
+ ;; Truncate output of previous dead processes.
+ (when (and eat-term-scrollback-size
+ (< eat-term-scrollback-size
+ (- (point) (point-min))))
+ (delete-region
+ (point-min)
+ (max (point-min)
+ (- (eat-term-display-beginning eat-terminal)
+ eat-term-scrollback-size))))
+ (setq eat--shell-prompt-annotation-correction-timer
+ (run-with-timer
+ eat-shell-prompt-annotation-correction-delay
+ nil #'eat--correct-shell-prompt-mark-overlays
+ buffer))
+ (add-text-properties
+ (eat-term-beginning eat-terminal)
+ (eat-term-end eat-terminal)
+ `( read-only t field eat-terminal
+ ,@(when eat--line-mode
+ '(front-sticky t rear-nonsticky t))))))
+ (eat--line-mode-do-toggles)
+ (funcall eat--synchronize-scroll-function sync-windows))
+ (run-hooks 'eat-update-hook))))
+
+(defun eat--filter (process output)
+ "Handle OUTPUT from PROCESS."
+ (when (buffer-live-p (process-buffer process))
+ (with-current-buffer (process-buffer process)
+ (when eat--process-output-queue-timer
+ (cancel-timer eat--process-output-queue-timer))
+ (when eat--shell-prompt-annotation-correction-timer
+ (cancel-timer eat--shell-prompt-annotation-correction-timer))
+ (unless eat--output-queue-first-chunk-time
+ (setq eat--output-queue-first-chunk-time (current-time)))
+ (push output eat--pending-output-chunks)
+ (unless (eq eat--output-queue-first-chunk-time t)
+ (let ((time-left
+ (- eat-maximum-latency
+ (float-time
+ (time-subtract
+ nil eat--output-queue-first-chunk-time)))))
+ (if (<= time-left 0)
+ (eat--process-output-queue (current-buffer))
+ (setq eat--process-output-queue-timer
+ (run-with-timer
+ (min time-left eat-minimum-latency) nil
+ #'eat--process-output-queue
+ (current-buffer)))))))))
+
+(defun eat--sentinel (process message)
+ "Sentinel for Eat buffers.
+
+PROCESS is the process and MESSAGE is the description of what happened
+to it."
+ (let ((buffer (process-buffer process)))
+ (when (memq (process-status process) '(signal exit))
+ (if (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (let ((inhibit-read-only t)
+ ;; We're is going to write outside of the terminal,
+ ;; so we won't synchronize buffer scroll here as we
+ ;; will set the buffer point automatically by
+ ;; writing to the buffer.
+ (eat--synchronize-scroll-function #'ignore))
+ (when eat--process-output-queue-timer
+ (cancel-timer eat--process-output-queue-timer)
+ (setq eat--process-output-queue-timer nil))
+ (eat--process-output-queue buffer)
+ (when eat--shell-prompt-annotation-correction-timer
+ (cancel-timer
+ eat--shell-prompt-annotation-correction-timer)
+ (setq eat--shell-prompt-annotation-correction-timer
+ nil))
+ (when eat-enable-shell-prompt-annotation
+ (eat--correct-shell-prompt-mark-overlays buffer)
+ (setq eat--shell-command-status 0)
+ (setq eat--shell-prompt-begin nil)
+ (setq eat--shell-prompt-mark nil)
+ (setq eat--shell-prompt-mark-overlays nil))
+ (when eat--line-mode
+ (eat--line-mode -1)
+ (delete-region (eat-term-end eat-terminal)
+ (point-max)))
+ (eat-emacs-mode)
+ (remove-text-properties
+ (eat-term-beginning eat-terminal)
+ (eat-term-end eat-terminal)
+ '(read-only nil field nil))
+ (eat-term-delete eat-terminal)
+ (setq eat-terminal nil)
+ (eat--set-cursor nil :default)
+ (eat--grab-mouse nil nil)
+ (goto-char (point-max))
+ (insert "\nProcess " (process-name process) " "
+ message)
+ (setq buffer-read-only nil))
+ (run-hook-with-args 'eat-exit-hook process)
+ (delete-process process))
+ (set-process-buffer process nil)))))
+
+(defun eat--adjust-process-window-size (process windows)
+ "Resize process window and terminal. Return new dimensions.
+
+PROCESS is the process whose window to resize, and WINDOWS is the list
+of window displaying PROCESS's buffer."
+ (let ((size (funcall window-adjust-process-window-size-function
+ process windows)))
+ (when size
+ (let ((width (max (car size) 1))
+ (height (max (cdr size) 1))
+ (inhibit-read-only t)
+ (sync-windows (eat--synchronize-scroll-windows)))
+ (eat-term-resize eat-terminal width height)
+ (eat-term-redisplay eat-terminal)
+ (funcall eat--synchronize-scroll-function sync-windows))
+ (pcase major-mode
+ ('eat-mode
+ (run-hooks 'eat-update-hook))
+ ('eshell-mode
+ (run-hooks 'eat-eshell-update-hook))))
+ size))
+
+(defun eat--kill-buffer (_process)
+ "Kill current buffer."
+ (kill-buffer (current-buffer)))
+
+;; Adapted from Term.
+(defun eat-exec (buffer name command startfile switches)
+ "Start up a process in BUFFER for Eat mode.
+
+Run COMMAND with SWITCHES. Set NAME as the name of the process.
+Blast any old process running in the buffer. Don't set the buffer
+mode. You can use this to cheaply run a series of processes in the
+same Eat buffer. The hook `eat-exec-hook' is run after each exec."
+ (with-current-buffer buffer
+ (let ((inhibit-read-only t))
+ (when-let* ((eat-terminal)
+ (proc (eat-term-parameter
+ eat-terminal 'eat--process)))
+ (remove-hook 'eat-exit-hook #'eat--kill-buffer t)
+ (delete-process proc))
+ ;; Ensure final newline.
+ (goto-char (point-max))
+ (unless (or (= (point-min) (point-max))
+ (= (char-before (point-max)) ?\n))
+ (insert ?\n))
+ (unless (= (point-min) (point-max))
+ (insert "\n\n"))
+ (setq eat-terminal (eat-term-make buffer (point)))
+ (eat-semi-char-mode)
+ (when-let* ((window (get-buffer-window nil t)))
+ (with-selected-window window
+ (eat-term-resize eat-terminal (window-max-chars-per-line)
+ (floor (window-screen-lines)))))
+ (setf (eat-term-parameter eat-terminal 'input-function)
+ #'eat--send-input)
+ (setf (eat-term-parameter eat-terminal 'set-cursor-function)
+ #'eat--set-cursor)
+ (setf (eat-term-parameter eat-terminal 'grab-mouse-function)
+ #'eat--grab-mouse)
+ (setf (eat-term-parameter
+ eat-terminal 'manipulate-selection-function)
+ #'eat--manipulate-kill-ring)
+ (setf (eat-term-parameter eat-terminal 'ring-bell-function)
+ #'eat--bell)
+ (setf (eat-term-parameter eat-terminal 'set-cwd-function)
+ #'eat--set-cwd)
+ (setf (eat-term-parameter eat-terminal 'ui-command-function)
+ #'eat--handle-uic)
+ (eat--set-term-sixel-params)
+ ;; Crank up a new process.
+ (let* ((size (eat-term-size eat-terminal))
+ (process-environment
+ (nconc
+ (list
+ (concat "TERM=" (eat-term-name))
+ (concat "TERMINFO=" eat-term-terminfo-directory)
+ (concat "INSIDE_EMACS=" eat-term-inside-emacs)
+ (concat "EAT_SHELL_INTEGRATION_DIR="
+ eat-term-shell-integration-directory))
+ process-environment))
+ (process-connection-type t)
+ ;; We should suppress conversion of end-of-line format.
+ (inhibit-eol-conversion t)
+ (process
+ (make-process
+ :name name
+ :buffer buffer
+ :command `("/usr/bin/env" "sh" "-c"
+ ,(format "stty -nl echo rows %d columns \
+%d sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
+ (cdr size) (car size)
+ null-device)
+ ".."
+ ,command ,@switches)
+ :filter #'eat--filter
+ :sentinel #'eat--sentinel
+ :file-handler t)))
+ (process-put process 'adjust-window-size-function
+ #'eat--adjust-process-window-size)
+ (set-process-query-on-exit-flag
+ process eat-query-before-killing-running-terminal)
+ ;; Jump to the end, and set the process mark.
+ (goto-char (point-max))
+ (set-marker (process-mark process) (point))
+ (setf (eat-term-parameter eat-terminal 'eat--process)
+ process)
+ (setf (eat-term-parameter eat-terminal 'eat--input-process)
+ process)
+ (setf (eat-term-parameter eat-terminal 'eat--output-process)
+ process)
+ (when eat-kill-buffer-on-exit
+ (add-hook 'eat-exit-hook #'eat--kill-buffer 90 t))
+ ;; Feed it the startfile.
+ (when startfile
+ ;; This is guaranteed to wait long enough
+ ;; but has bad results if the shell does not prompt at all
+ ;; (while (= size (buffer-size))
+ ;; (sleep-for 1))
+ ;; I hope 1 second is enough!
+ (sleep-for 1)
+ (goto-char (point-max))
+ (insert-file-contents startfile)
+ (process-send-string
+ process (delete-and-extract-region (point) (point-max)))))
+ (eat-term-redisplay eat-terminal))
+ (run-hook-with-args 'eat-exec-hook (eat-term-parameter
+ eat-terminal 'eat--process))
+ buffer))
+
+\f
+;;;;; Entry Points.
+
+(defun eat-make (name program &optional startfile &rest switches)
+ "Make a Eat process NAME in a buffer, running PROGRAM.
+
+The name of the buffer is made by surrounding NAME with `*'s. If
+there is already a running process in that buffer, it is not
+restarted. Optional third arg STARTFILE is the name of a file to send
+the contents of to the process. SWITCHES are the arguments to
+PROGRAM."
+ (let ((buffer (get-buffer-create (concat "*" name "*"))))
+ ;; If no process, or nuked process, crank up a new one and put
+ ;; buffer in Eat mode. Otherwise, leave buffer and existing
+ ;; process alone.
+ (when (not (let ((proc (get-buffer-process buffer)))
+ (and proc (memq (process-status proc)
+ '(run stop open listen connect)))))
+ (with-current-buffer buffer
+ (eat-mode))
+ (eat-exec buffer name program startfile switches))
+ buffer))
+
+(defun eat--1 (program arg display-buffer-fn)
+ "Start a new Eat terminal emulator in a buffer.
+
+PROGRAM and ARG is same as in `eat' and `eat-other-window'.
+DISPLAY-BUFFER-FN is the function to display the buffer."
+ (let ((program (or program (or explicit-shell-file-name
+ (getenv "ESHELL")
+ shell-file-name)))
+ (buffer
+ (cond
+ ((numberp arg)
+ (get-buffer-create (format "%s<%d>" eat-buffer-name arg)))
+ (arg
+ (generate-new-buffer eat-buffer-name))
+ (t
+ (get-buffer-create eat-buffer-name)))))
+ (with-current-buffer buffer
+ (unless (eq major-mode #'eat-mode)
+ (eat-mode))
+ (funcall display-buffer-fn buffer)
+ (unless (and eat-terminal
+ (eat-term-parameter eat-terminal 'eat--process))
+ (eat-exec buffer (buffer-name) "/usr/bin/env" nil
+ (list "sh" "-c" program)))
+ buffer)))
+
+;;;###autoload
+(defun eat (&optional program arg)
+ "Start a new Eat terminal emulator in a buffer.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG (like \\[universal-argument] 42 \\[eat]),
+switch to the session with that number, or create it if it doesn't
+already exist.
+
+With double prefix argument ARG, ask for the program to run and run it
+in a newly created session.
+
+PROGRAM can be a shell command."
+ (interactive
+ (list (when (equal current-prefix-arg '(16))
+ (read-shell-command "Run program: "
+ (or explicit-shell-file-name
+ (getenv "ESHELL")
+ shell-file-name)))
+ current-prefix-arg))
+ (eat--1 program arg #'pop-to-buffer-same-window))
+
+;;;###autoload
+(defun eat-other-window (&optional program arg)
+ "Start a new Eat terminal emulator in a buffer in another window.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG switch to the session with that number, or
+create it if it doesn't already exist.
+
+With double prefix argument ARG, ask for the program to run and run it
+in a newly created session.
+
+PROGRAM can be a shell command."
+ (interactive
+ (list (when (equal current-prefix-arg '(16))
+ (read-shell-command "Run program: "
+ (or explicit-shell-file-name
+ (getenv "ESHELL")
+ shell-file-name)))
+ current-prefix-arg))
+ (eat--1 program arg #'pop-to-buffer))
+
+\f
+;;;; Eshell integration.
+
+;;;;; Input.
+
+;; When changing these keymaps, be sure to update the manual, README
+;; and commentary.
+(defvar eat-eshell-emacs-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [?\C-c ?\C-j] #'eat-eshell-semi-char-mode)
+ (define-key map [remap eshell-toggle-direct-send] ; C-c M-d
+ #'eat-eshell-char-mode)
+ (define-key map [remap undo] #'undefined) ; Disable `undo'.
+ (define-key map [xterm-paste] #'ignore)
+ map)
+ "Keymap for Eat Eshell \"emacs\" mode.")
+
+(defun eat--eshell-prepare-semi-char-mode-map ()
+ "Prepare `eat-eshell-semi-char-mode-map'."
+ (let ((map (eat-term-make-keymap
+ #'eat-self-input '(:ascii :arrow :navigation)
+ `([?\C-c] [?\C-q] [?\C-y] [?\e ?y]
+ ,@eat-eshell-semi-char-non-bound-keys))))
+ (define-key map [?\C-q] #'eat-quoted-input)
+ (define-key map [?\C-y] #'eat-yank)
+ (define-key map [?\M-y] #'eat-yank-from-kill-ring)
+ (define-key map [?\C-c ?\C-e] #'eat-eshell-emacs-mode)
+ (define-key map [S-insert] #'eat-yank)
+ (define-key map [remap insert-char] #'eat-input-char)
+ (define-key map [remap mouse-yank-primary]
+ #'eat-mouse-yank-primary)
+ (define-key map [remap mouse-yank-secondary]
+ #'eat-mouse-yank-secondary)
+ (define-key map [xterm-paste] #'eat-xterm-paste)
+ map))
+
+(defvar eat-eshell-semi-char-mode-map
+ (ignore-errors
+ (eat--eshell-prepare-semi-char-mode-map))
+ "Keymap for Eat Eshell semi-char mode.")
+
+(defun eat-eshell-update-semi-char-mode-map ()
+ "Update \"semi-char\" keybinding mode's keymap in Eshell."
+ (setq eat-eshell-semi-char-mode-map
+ (eat--eshell-prepare-semi-char-mode-map)))
+
+(defvar eat-eshell-char-mode-map
+ (let ((map (eat-term-make-keymap
+ #'eat-self-input '(:ascii :arrow :navigation :function)
+ '([?\e ?\C-m]))))
+ (define-key map [?\C-\M-m] #'eat-eshell-semi-char-mode)
+ (define-key map [xterm-paste] #'eat-xterm-paste)
+ map)
+ "Keymap for Eat Eshell char mode.")
+
+(define-minor-mode eat--eshell-process-running-mode
+ "Minor mode for \"emacs\" mode keymap when process is running."
+ :interactive nil
+ :keymap eat-eshell-emacs-mode-map)
+
+(define-minor-mode eat--eshell-semi-char-mode
+ "Minor mode for semi-char mode keymap."
+ :interactive nil
+ :keymap eat-eshell-semi-char-mode-map
+ ;; HACK: Some keys like `C-c' are overriden by other keymaps
+ ;; (possibly by the keymaps of other minor modes), so we also put
+ ;; the keymap to `minor-mode-overriding-map-alist' to make Emacs
+ ;; prioritize us.
+ (setq minor-mode-overriding-map-alist
+ (delete (cons #'eat--eshell-semi-char-mode
+ eat-eshell-semi-char-mode-map)
+ minor-mode-overriding-map-alist))
+ (when eat--eshell-semi-char-mode
+ (push (cons #'eat--eshell-semi-char-mode
+ eat-eshell-semi-char-mode-map)
+ minor-mode-overriding-map-alist)))
+
+(define-minor-mode eat--eshell-char-mode
+ "Minor mode for char mode keymap."
+ :interactive nil
+ :keymap eat-eshell-char-mode-map
+ ;; HACK: Some keys like `C-c' are overriden by other keymaps
+ ;; (possibly by the keymaps of other minor modes), so we also put
+ ;; the keymap to `minor-mode-overriding-map-alist' to make Emacs
+ ;; prioritize us.
+ (setq minor-mode-overriding-map-alist
+ (delete (cons #'eat--eshell-char-mode
+ eat-eshell-char-mode-map)
+ minor-mode-overriding-map-alist))
+ (when eat--eshell-char-mode
+ (push (cons #'eat--eshell-char-mode eat-eshell-char-mode-map)
+ minor-mode-overriding-map-alist)))
+
+(defun eat-eshell-emacs-mode ()
+ "Switch to Emacs keybindings mode."
+ (interactive)
+ (eat--eshell-semi-char-mode -1)
+ (eat--eshell-char-mode -1)
+ (setq buffer-read-only t)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (force-mode-line-update))
+
+(defun eat-eshell-semi-char-mode ()
+ "Switch to semi-char mode."
+ (interactive)
+ (when eat-terminal
+ (setq buffer-read-only nil)
+ (eat--eshell-char-mode -1)
+ (eat--eshell-semi-char-mode +1)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (force-mode-line-update)))
+
+(defun eat-eshell-char-mode ()
+ "Switch to char mode."
+ (interactive)
+ (when eat-terminal
+ (setq buffer-read-only nil)
+ (eat--eshell-semi-char-mode -1)
+ (eat--eshell-char-mode +1)
+ (eat--grab-mouse nil eat--mouse-grabbing-type)
+ (force-mode-line-update)))
+
+\f
+;;;;; Process Handling.
+
+(defvar eat--eshell-invocation-directory nil
+ "The directory from where the current process was started.")
+
+(defvar eshell-last-output-start) ; In `esh-mode'.
+(defvar eshell-last-output-end) ; In `esh-mode'.
+(defvar eshell-output-filter-functions) ; In `esh-mode'.
+(defvar eshell-parent-buffer) ; In `em-term'.
+(declare-function eshell-head-process "esh-cmd" ())
+(declare-function eshell-resume-eval "esh-cmd" ())
+
+(defun eat--eshell-handle-uic (_ cmd)
+ "Handle UI Command sequence CMD."
+ (pcase cmd
+ ;; UIC e ; A ; <t> ; <s> ST.
+ ((rx string-start "e;A;"
+ (let host (zero-or-more (not (any ?\;))))
+ ?\; (let path (zero-or-more anything))
+ string-end)
+ (eat--set-cwd-uic host path))
+ ;; UIC e ; F ; <t> ST.
+ ((rx string-start "e;F;"
+ (let cmd (zero-or-more anything))
+ string-end)
+ (eat--set-cmd cmd))
+ ;; UIC e ; I ; 0 ; <t> ST.
+ ((rx string-start "e;I;0;" (zero-or-more anything) string-end)
+ (eat-term-send-string eat-terminal "\e]51;e;I;0\e\\"))
+ ;; UIC e ; M ; ... ST.
+ ((rx string-start "e;M;"
+ (let msg (zero-or-more anything))
+ string-end)
+ (apply #'eat--handle-message (string-split msg ";")))
+ ;; Other sequences are ignored.
+ ))
+
+(defun eat--eshell-term-name (&rest _)
+ "Return the value of `TERM' environment variable for Eshell."
+ (eat-term-name))
+
+(defun eat--eshell-output-filter ()
+ "Handle output from subprocess."
+ (let ((inhibit-quit t) ; Don't disturb!
+ (str (buffer-substring-no-properties
+ eshell-last-output-start
+ eshell-last-output-end)))
+ (let ((inhibit-read-only t))
+ (delete-region eshell-last-output-start eshell-last-output-end))
+ (let ((sync-windows (eat--synchronize-scroll-windows))
+ (inhibit-read-only t))
+ (eat-term-process-output eat-terminal str)
+ (eat-term-redisplay eat-terminal)
+ (funcall eat--synchronize-scroll-function sync-windows))
+ (let ((inhibit-read-only t))
+ (let ((end (eat-term-end eat-terminal)))
+ (set-marker eshell-last-output-start end)
+ (set-marker eshell-last-output-end end)
+ (set-marker (process-mark
+ (eat-term-parameter
+ eat-terminal 'eat--output-process))
+ end))))
+ (run-hooks 'eat-eshell-update-hook))
+
+(defun eat--eshell-setup-proc-and-term (proc)
+ "Setup process PROC and a new terminal for it."
+ (unless eat-terminal
+ (process-put proc 'adjust-window-size-function
+ #'eat--adjust-process-window-size)
+ (setq eat-terminal
+ (eat-term-make (current-buffer)
+ (if (marker-buffer (process-mark proc))
+ (process-mark proc)
+ (point-max))))
+ (set-marker (process-mark proc) (eat-term-end eat-terminal))
+ (setf (eat-term-parameter eat-terminal 'input-function)
+ #'eat--send-input)
+ (setf (eat-term-parameter eat-terminal 'set-cursor-function)
+ #'eat--set-cursor)
+ (setf (eat-term-parameter eat-terminal 'grab-mouse-function)
+ #'eat--grab-mouse)
+ (setf (eat-term-parameter
+ eat-terminal 'manipulate-selection-function)
+ #'eat--manipulate-kill-ring)
+ (setf (eat-term-parameter eat-terminal 'ring-bell-function)
+ #'eat--bell)
+ (setf (eat-term-parameter eat-terminal 'set-cwd-function)
+ #'eat--set-cwd)
+ (setf (eat-term-parameter eat-terminal 'ui-command-function)
+ #'eat--eshell-handle-uic)
+ (eat--set-term-sixel-params)
+ (setf (eat-term-parameter eat-terminal 'eat--process) proc)
+ (unless (eval-when-compile (>= emacs-major-version 29))
+ (setf (eat-term-parameter eat-terminal 'eat--input-process)
+ proc))
+ (setf (eat-term-parameter eat-terminal 'eat--output-process) proc)
+ (when-let* ((window (get-buffer-window nil t)))
+ (with-selected-window window
+ (eat-term-resize eat-terminal (window-max-chars-per-line)
+ (floor (window-screen-lines)))))
+ (eat-term-redisplay eat-terminal)
+ (setq-local eshell-output-filter-functions
+ '(eat--eshell-output-filter))
+ (eat--eshell-process-running-mode +1)
+ (eat-eshell-semi-char-mode)
+ (run-hooks 'eat-eshell-exec-hook)))
+
+(defun eat--eshell-cleanup ()
+ "Cleanup everything."
+ (when eat-terminal
+ (let ((inhibit-read-only t))
+ (cd-absolute eat--eshell-invocation-directory)
+ (goto-char (eat-term-end eat-terminal))
+ (unless (or (= (point) (point-min))
+ (= (char-before) ?\n))
+ (insert ?\n))
+ (set-marker eshell-last-output-start (point))
+ (set-marker eshell-last-output-end (point))
+ (eat--cursor-blink-mode -1)
+ (eat--grab-mouse nil nil)
+ (set-process-filter
+ (eat-term-parameter
+ eat-terminal 'eat--output-process)
+ (if (eval-when-compile (< emacs-major-version 30))
+ #'eshell-output-filter
+ #'eshell-interactive-process-filter))
+ (eat-term-delete eat-terminal)
+ (setq eat-terminal nil)
+ (kill-local-variable 'eshell-output-filter-functions)
+ (eat--eshell-semi-char-mode -1)
+ (eat--eshell-char-mode -1)
+ (eat--eshell-process-running-mode -1)
+ (setq buffer-read-only nil))
+ (run-hooks 'eat-eshell-exit-hook)))
+
+(declare-function eshell-output-filter "esh-mode" (process string))
+(declare-function eshell-interactive-process-filter "esh-mode"
+ (process string))
+
+(defun eat--eshell-process-output-queue (process buffer)
+ "Process the output queue on BUFFER from PROCESS."
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (when eat--process-output-queue-timer
+ (cancel-timer eat--process-output-queue-timer))
+ (setq eat--output-queue-first-chunk-time nil)
+ (while eat--pending-output-chunks
+ (let ((queue eat--pending-output-chunks)
+ (eat--output-queue-first-chunk-time t))
+ (setq eat--pending-output-chunks nil)
+ (if (eval-when-compile (< emacs-major-version 27))
+ (eshell-output-filter
+ process (string-join (nreverse queue)))
+ (combine-change-calls
+ (eat-term-beginning eat-terminal)
+ (eat-term-end eat-terminal)
+ ;; TODO: Is `string-join' OK or should we use a loop?
+ (if (eval-when-compile (< emacs-major-version 30))
+ (eshell-output-filter
+ process (string-join (nreverse queue)))
+ (eshell-interactive-process-filter
+ process (string-join (nreverse queue)))))))))))
+
+(defun eat--eshell-filter (process string)
+ "Process output STRING from PROCESS."
+ (when (buffer-live-p (process-buffer process))
+ (with-current-buffer (process-buffer process)
+ (when eat--process-output-queue-timer
+ (cancel-timer eat--process-output-queue-timer))
+ (unless eat--output-queue-first-chunk-time
+ (setq eat--output-queue-first-chunk-time (current-time)))
+ (push string eat--pending-output-chunks)
+ (unless (eq eat--output-queue-first-chunk-time t)
+ (let ((time-left
+ (- eat-maximum-latency
+ (float-time
+ (time-subtract
+ nil eat--output-queue-first-chunk-time)))))
+ (if (<= time-left 0)
+ (eat--eshell-process-output-queue
+ process (current-buffer))
+ (setq eat--process-output-queue-timer
+ (run-with-timer
+ (min time-left eat-minimum-latency) nil
+ #'eat--eshell-process-output-queue process
+ (current-buffer)))))))))
+
+(declare-function eshell-sentinel "esh-proc" (proc string))
+
+(defun eat--eshell-sentinel (process message)
+ "Process status message MESSAGE from PROCESS."
+ (when (buffer-live-p (process-buffer process))
+ (with-current-buffer (process-buffer process)
+ ;; Eshell is going to write outside of the terminal, so we won't
+ ;; synchronize buffer scroll here as it'll interfare with
+ ;; Eshell.
+ (cl-letf* ((eat--synchronize-scroll-function #'ignore)
+ (process-send-string
+ (symbol-function #'process-send-string))
+ ((symbol-function #'process-send-string)
+ (lambda (proc string)
+ (when (or (not (eq proc process))
+ (process-live-p proc))
+ (funcall process-send-string proc string)))))
+ (eat--eshell-process-output-queue process (current-buffer)))
+ (when (memq (process-status process) '(signal exit))
+ (eat--eshell-cleanup))))
+ (eshell-sentinel process message))
+
+(declare-function eshell-search-path "esh-ext" (name))
+(declare-function eshell-interactive-output-p "esh-io"
+ (&optional index handles))
+(defvar eshell-current-subjob-p) ; In `esh-proc'.
+
+;; HACK: This is a dirty hack, it can break easily.
+(defun eat--eshell-adjust-make-process-args (fn command args)
+ "Setup an environment to adjust `make-process' arguments.
+
+Call FN with COMMAND and ARGS, and whenever `make-process' is called,
+modify its argument to change the filter, the sentinel and invoke
+`stty' from the new process."
+ (if (or eshell-current-subjob-p
+ (not (eshell-interactive-output-p))
+ (and (not (eshell-search-path "stty"))
+ (pcase eat-eshell-fallback-if-stty-not-available
+ ('nil nil)
+ ('t t)
+ ('ask (not (y-or-n-p "The program stty can't be \
+found, input won't be shown if terminal emulation is enabled. \
+Disable terminal emulation? ")))
+ ((and (pred functionp) function)
+ (apply function command args)))))
+ (funcall fn command args)
+ (let ((hook (lambda (proc)
+ (set-process-filter proc #'eat--eshell-filter)
+ (set-process-sentinel proc #'eat--eshell-sentinel)
+ (eat--eshell-setup-proc-and-term proc))))
+ (add-hook 'eshell-exec-hook hook 99)
+ (unwind-protect
+ (cond
+ ;; Emacs 29 and above.
+ ((eval-when-compile (>= emacs-major-version 29))
+ (cl-letf*
+ ((make-process (symbol-function #'make-process))
+ ((symbol-function #'make-process)
+ (lambda (&rest plist)
+ ;; Make sure we don't attack wrong process.
+ (if (not (equal
+ (plist-get plist :command)
+ (cons (file-local-name
+ (expand-file-name command))
+ args)))
+ (apply make-process plist)
+ (setf (plist-get plist :command)
+ `("/usr/bin/env" "sh" "-c"
+ ,(format "stty -nl echo rows %d columns\
+ %d sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
+ (floor (window-screen-lines))
+ (window-max-chars-per-line)
+ null-device)
+ ".." ,@(plist-get plist :command)))
+ (apply make-process plist)))))
+ (funcall fn command args)))
+ ;; Emacs 28.
+ (t
+ (cl-letf*
+ ((start-file-process
+ (symbol-function #'start-file-process))
+ ((symbol-function #'start-file-process)
+ (lambda (name buffer &rest command)
+ (apply start-file-process name buffer
+ "/usr/bin/env" "sh" "-c"
+ (format "stty -nl echo rows %d columns %d \
+sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
+ (floor (window-screen-lines))
+ (window-max-chars-per-line)
+ null-device)
+ ".." command))))
+ (funcall fn command args))))
+ (remove-hook 'eshell-exec-hook hook)))))
+
+(defun eat--eshell-set-input-process (&rest _)
+ "Set the process that gets user input."
+ (when eat-terminal
+ (setf (eat-term-parameter eat-terminal 'eat--input-process)
+ (eshell-head-process))))
+
+\f
+;;;;; Minor Modes.
+
+(defun eat--eshell-synchronize-scroll (windows)
+ "Synchronize scrolling and point between terminal and WINDOWS.
+
+WINDOWS is a list of windows. WINDOWS may also contain the special
+symbol `buffer', in which case the point of current buffer is set."
+ (dolist (window windows)
+ (if (eq window 'buffer)
+ (goto-char (eat-term-display-cursor eat-terminal))
+ (with-selected-window window
+ (set-window-point nil (eat-term-display-cursor eat-terminal))
+ (recenter
+ (- (1+ (how-many "\n" (eat-term-display-cursor eat-terminal)
+ (eat-term-end eat-terminal)))))))))
+
+(defun eat--eshell-update-cwd ()
+ "Update the current working directory."
+ (setq eat--eshell-invocation-directory default-directory))
+
+(defvar eshell-variable-aliases-list) ; In `esh-var'.
+
+(define-minor-mode eat--eshell-local-mode
+ "Toggle Eat terminal emulation is Eshell."
+ :interactive nil
+ (let ((locals '(cursor-type
+ glyphless-char-display
+ scroll-margin
+ hscroll-margin
+ track-mouse
+ filter-buffer-substring-function
+ eat-terminal
+ eat--synchronize-scroll-function
+ eat--mouse-grabbing-type
+ eat--pending-output-chunks
+ eat--output-queue-first-chunk-time
+ eat--process-output-queue-timer
+ eat--eshell-invocation-directory)))
+ (cond
+ (eat--eshell-local-mode
+ (mapc #'make-local-variable locals)
+ (setq scroll-margin 0)
+ (setq hscroll-margin 0)
+ (setq eat--synchronize-scroll-function
+ #'eat--eshell-synchronize-scroll)
+ (setq filter-buffer-substring-function
+ #'eat--filter-buffer-substring)
+ (make-local-variable 'eshell-variable-aliases-list)
+ (setq eshell-variable-aliases-list
+ `(("TERM" eat--eshell-term-name t)
+ ("TERMINFO" eat-term-terminfo-directory t)
+ ("INSIDE_EMACS" eat-term-inside-emacs t)
+ ("EAT_SHELL_INTEGRATION_DIR"
+ eat-term-shell-integration-directory t)
+ ,@eshell-variable-aliases-list))
+ ;; Make sure glyphless character don't display a huge box glyph,
+ ;; that would break the display.
+ (eat--setup-glyphless-chars)
+ (eat--eshell-update-cwd)
+ (when eat-enable-blinking-text
+ (eat-blink-mode +1)))
+ (t
+ (when eat-enable-blinking-text
+ (eat-blink-mode -1))
+ (mapc #'kill-local-variable locals)
+ (setq eshell-variable-aliases-list
+ (cl-delete-if
+ (lambda (elem)
+ (member elem
+ '(("TERM" eat--eshell-term-name t)
+ ("TERMINFO" eat-term-terminfo-directory t)
+ ("INSIDE_EMACS" eat-term-inside-emacs t)
+ ("EAT_SHELL_INTEGRATION_DIR"
+ eat-term-shell-integration-directory t))))
+ eshell-variable-aliases-list))))))
+
+(declare-function eshell-gather-process-output "esh-proc"
+ (command args))
+(defvar eshell-last-async-proc) ; In `esh-cmd'.
+(defvar eshell-last-async-procs) ; In `esh-cmd'.
+
+;;;###autoload
+(define-minor-mode eat-eshell-mode
+ "Toggle Eat terminal emulation in Eshell."
+ :global t
+ :lighter (eat--eshell-local-mode
+ (" Eat-Eshell"
+ (:eval
+ (when eat-terminal
+ (cond
+ (eat--eshell-semi-char-mode
+ `("["
+ (:propertize
+ "semi-char"
+ help-echo
+ ,(concat "mouse-1: Switch to char mode, "
+ "mouse-3: Switch to emacs mode")
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-eshell-char-mode)
+ (down-mouse-3 . eat-eshell-emacs-mode)))))
+ "]"))
+ (eat--eshell-char-mode
+ '("["
+ (:propertize
+ "char"
+ help-echo
+ ,(concat "mouse-1: Switch to semi-char mode, "
+ "mouse-3: Switch to emacs mode")
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-eshell-semi-char-mode)
+ (down-mouse-3 . eat-eshell-emacs-mode)))))
+ "]"))
+ (t
+ `("["
+ (:propertize
+ "emacs"
+ help-echo
+ ,(concat "mouse-1: Switch to semi-char mode, "
+ "mouse-3: Switch to char mode")
+ mouse-face mode-line-highlight
+ local-map
+ (keymap
+ (mode-line
+ . (keymap
+ (down-mouse-1 . eat-eshell-semi-char-mode)
+ (down-mouse-3 . eat-eshell-char-mode)))))
+ "]")))))))
+ :group 'eat-eshell
+ (cond
+ (eat-eshell-mode
+ (let ((buffers nil))
+ (setq eat-eshell-mode nil)
+ (require 'esh-mode)
+ (require 'esh-proc)
+ (require 'esh-var)
+ (require 'esh-cmd)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (eq major-mode #'eshell-mode)
+ (when (if (eval-when-compile (< emacs-major-version 29))
+ (bound-and-true-p eshell-last-async-proc)
+ (bound-and-true-p eshell-last-async-procs))
+ (user-error
+ (concat "Can't toggle Eat Eshell mode while"
+ " any Eshell process is running")))
+ (push buffer buffers))))
+ (setq eat-eshell-mode t)
+ (dolist (buffer buffers)
+ (with-current-buffer buffer
+ (eat--eshell-local-mode +1))))
+ (add-hook 'eshell-mode-hook #'eat--eshell-local-mode)
+ (add-hook 'eshell-directory-change-hook #'eat--eshell-update-cwd)
+ (advice-add #'eshell-gather-process-output :around
+ #'eat--eshell-adjust-make-process-args)
+ (when (eval-when-compile (>= emacs-major-version 29))
+ (advice-add #'eshell-resume-eval :after
+ #'eat--eshell-set-input-process)))
+ (t
+ (let ((buffers nil))
+ (setq eat-eshell-mode t)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (and (eq major-mode #'eshell-mode)
+ eat--eshell-local-mode)
+ (when (if (eval-when-compile (< emacs-major-version 29))
+ (bound-and-true-p eshell-last-async-proc)
+ (bound-and-true-p eshell-last-async-procs))
+ (user-error
+ (concat "Can't toggle Eat Eshell mode while"
+ " any Eshell process is running")))
+ (push buffer buffers))))
+ (setq eat-eshell-mode nil)
+ (dolist (buffer buffers)
+ (with-current-buffer buffer
+ (eat--eshell-local-mode -1))))
+ (remove-hook 'eshell-mode-hook #'eat--eshell-local-mode)
+ (remove-hook 'eshell-directory-change-hook
+ #'eat--eshell-update-cwd)
+ (advice-remove #'eshell-gather-process-output
+ #'eat--eshell-adjust-make-process-args)
+ (when (eval-when-compile (>= emacs-major-version 29))
+ (advice-remove #'eshell-resume-eval
+ #'eat--eshell-set-input-process)))))
+
+\f
+;;;; Eshell Visual Command Handling.
+
+(defvar eshell-destroy-buffer-when-process-dies) ; In `em-term'.
+
+;; Adapted from `em-term'.
+(defun eat--eshell-visual-sentinel (proc _msg)
+ "Clean up the buffer visiting PROC.
+
+If `eshell-destroy-buffer-when-process-dies' is non-nil, destroy
+the buffer.
+
+MSG describes PROC's status."
+ (when eshell-destroy-buffer-when-process-dies
+ (let ((proc-buf (process-buffer proc)))
+ (when (and proc-buf (buffer-live-p proc-buf)
+ (not (eq 'run (process-status proc)))
+ (= (process-exit-status proc) 0))
+ (if (eq (current-buffer) proc-buf)
+ (when-let* ((buf (and (boundp 'eshell-parent-buffer)
+ (buffer-live-p eshell-parent-buffer)
+ eshell-parent-buffer)))
+ (switch-to-buffer buf)))
+ (kill-buffer proc-buf)))))
+
+(defvar eshell-interpreter-alist) ; In `esh-ext'.
+(declare-function eshell-find-interpreter "esh-ext"
+ (file args &optional no-examine-p))
+(declare-function eshell-stringify-list "esh-util" (args))
+
+(defun eat--eshell-exec-visual (&rest args)
+ "Run the specified PROGRAM in a terminal emulation buffer.
+
+ARGS are passed to the program. At the moment, no piping of input is
+allowed."
+ (require 'esh-ext)
+ (require 'esh-util)
+ (let* ((eshell-interpreter-alist nil)
+ (interp (eshell-find-interpreter (car args) (cdr args)))
+ (program (car interp))
+ (args (flatten-tree
+ (eshell-stringify-list (append (cdr interp)
+ (cdr args)))))
+ (eat-buf
+ (generate-new-buffer
+ (concat "*" (file-name-nondirectory program) "*")))
+ (eshell-buf (current-buffer)))
+ (with-current-buffer eat-buf
+ (switch-to-buffer eat-buf)
+ (eat-mode)
+ (setq-local eshell-parent-buffer eshell-buf)
+ (setq-local eat-kill-buffer-on-exit nil)
+ (eat-exec eat-buf program program nil args)
+ (let ((proc (get-buffer-process eat-buf)))
+ (if (and proc (eq 'run (process-status proc)))
+ (let ((sentinel (process-sentinel proc)))
+ (add-function :after (var sentinel)
+ #'eat--eshell-visual-sentinel)
+ (set-process-sentinel proc sentinel))
+ (error "Failed to invoke visual command")))
+ (eat-semi-char-mode)))
+ nil)
+
+(declare-function eshell-exec-visual "em-term" (&rest args))
+
+;;;###autoload
+(define-minor-mode eat-eshell-visual-command-mode
+ "Toggle running Eshell visual commands with Eat."
+ :group 'eat-eshell
+ :global t
+ (if eat-eshell-visual-command-mode
+ (advice-add #'eshell-exec-visual :override
+ #'eat--eshell-exec-visual)
+ (advice-remove #'eshell-exec-visual #'eat--eshell-exec-visual)))
+
+\f
+;;;; Project Integration.
+
+(declare-function project-root "project" (project))
+(declare-function project-prefixed-buffer-name "project" (mode))
+
+;;;###autoload
+(defun eat-project (&optional arg)
+ "Start Eat in the current project's root directory.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG (like
+\\[universal-argument] 42 \\[eat-project]), switch to the session with
+that number, or create it if it doesn't already exist."
+ (interactive "P")
+ (require 'project)
+ (let* ((default-directory (project-root (project-current t)))
+ (eat-buffer-name (project-prefixed-buffer-name "eat")))
+ (eat nil arg)))
+
+;;;###autoload
+(defun eat-project-other-window (&optional arg)
+ "Start Eat in the current project root directory in another window.
+
+Start a new Eat session, or switch to an already active session.
+Return the buffer selected (or created).
+
+With a non-numeric prefix ARG, create a new session.
+
+With a numeric prefix ARG (like
+\\[universal-argument] 42 \\[eat-project]), switch to the session with
+that number, or create it if it doesn't already exist."
+ (interactive "P")
+ (require 'project)
+ (let* ((default-directory (project-root (project-current t)))
+ (eat-buffer-name (project-prefixed-buffer-name "eat")))
+ (eat-other-window nil arg)))
+
+\f
+;;;; Tracing.
+
+;;;;; Recording Trace Data.
+
+(defconst eat--trace-recorded-variables
+ '(eat-term-scrollback-size
+ eat-enable-alternative-display)
+ "The variable to record in trace output.")
+
+(defvar eat--trace-output-buffer nil
+ "Buffer where the trace data is written to.")
+
+(defun eat--trace-log (time operation &rest args)
+ "Log TIME, OPERATION and ARGS into trace output.
+
+TIME defaults to the current time.
+
+The current buffer should be the trace output buffer. Move the point
+to the end of (accessible portion of) buffer."
+ (goto-char (point-max))
+ ;; Hope that `float-time' won't roll over while tracing. ;-)
+ (insert (replace-regexp-in-string
+ (rx (any (0 . 31)))
+ (lambda (string) (format "\\\\x%02x" (aref string 0)))
+ (format "%S" `(,(float-time time) ,operation ,@args)))
+ ?\n))
+
+(defun eat--trace-stop ()
+ "Stop tracing the terminal in current buffer."
+ (when eat--trace-output-buffer
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'finish)))
+ (remove-hook 'kill-buffer-hook #'eat--trace-stop t)
+ (kill-local-variable 'eat--trace-output-buffer))
+
+(defun eat--trace-exec (fn buffer name command startfile switches)
+ "Trace `eat-exec'.
+
+BUFFER is the buffer and COMMAND and SWITCHES are the invocation
+command. BUFFER, NAME, COMMAND, STARTFILE and SWITCHES are passed to
+FN, `eat-exec', which see."
+ (let ((time (current-time)))
+ (prog1
+ (funcall fn buffer name command startfile switches)
+ (let ((buf (generate-new-buffer
+ (format "*eat-trace %s*: %s"
+ (buffer-name buffer)
+ (mapconcat #'shell-quote-argument
+ (cons command switches) " "))))
+ (width nil)
+ (height nil)
+ (variables nil))
+ (with-current-buffer buffer
+ (setq-local eat--trace-output-buffer buf)
+ (add-hook 'kill-buffer-hook #'eat--trace-stop nil t)
+ (let ((size (eat-term-size eat-terminal)))
+ (setq width (car size))
+ (setq height (cdr size)))
+ (dolist (var eat--trace-recorded-variables)
+ (push (cons var (symbol-value var)) variables)))
+ (with-current-buffer buf
+ (when (fboundp 'lisp-data-mode) (lisp-data-mode))
+ (insert ";; -*- mode: lisp-data -*-\n")
+ (eat--trace-log time 'create 'eat width height
+ variables))))))
+
+(defun eat--trace-process-output-queue (fn buffer)
+ "Trace `eat--process-output-queue'.
+
+BUFFER is passed to FN, `eat--process-output-queue', which see."
+ (if (or (not (buffer-live-p buffer))
+ (not (buffer-local-value 'eat--trace-output-buffer buffer)))
+ (funcall fn buffer)
+ (cl-letf* ((eat-term-process-output
+ (symbol-function #'eat-term-process-output))
+ ((symbol-function #'eat-term-process-output)
+ (lambda (terminal output)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'output output)))
+ (funcall eat-term-process-output terminal output)))
+ (eat-term-redisplay
+ (symbol-function #'eat-term-redisplay))
+ ((symbol-function #'eat-term-redisplay)
+ (lambda (terminal)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'redisplay)))
+ (funcall eat-term-redisplay terminal))))
+ (funcall fn buffer))))
+
+(defun eat--trace-adjust-process-window-size (fn process windows)
+ "Trace `eat--adjust-process-window-size'.
+
+PROCESS and WINDOWS are passed to FN,
+`eat--adjust-process-window-size', which see."
+ (cl-letf*
+ ((eat-term-resize (symbol-function #'eat-term-resize))
+ ((symbol-function #'eat-term-resize)
+ (lambda (terminal width height)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'resize width height)))
+ (funcall eat-term-resize terminal width height)))
+ (eat-term-redisplay (symbol-function #'eat-term-redisplay))
+ ((symbol-function #'eat-term-redisplay)
+ (lambda (terminal)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'redisplay)))
+ (funcall eat-term-redisplay terminal))))
+ (funcall fn process windows)))
+
+(defun eat--trace-sentinel (fn &rest args)
+ "Trace `eat--sentinel'.
+
+Elements of ARGS are passed to FN, `eat--sentinel', which see."
+ (cl-letf* ((eat-term-delete (symbol-function #'eat-term-delete))
+ ((symbol-function #'eat-term-delete)
+ (lambda (terminal)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (eat--trace-stop))
+ (funcall eat-term-delete terminal))))
+ (apply fn args)))
+
+(defun eat--trace-reset (fn)
+ "Trace `eat-reset'.
+
+FN is original definition of `eat-reset'."
+ (cl-letf*
+ ((eat-term-reset (symbol-function #'eat-term-reset))
+ ((symbol-function #'eat-term-reset)
+ (lambda (terminal)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'reset)))
+ (funcall eat-term-reset terminal)))
+ (eat-term-redisplay (symbol-function #'eat-term-redisplay))
+ ((symbol-function #'eat-term-redisplay)
+ (lambda (terminal)
+ (when (buffer-live-p eat--trace-output-buffer)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'redisplay)))
+ (funcall eat-term-redisplay terminal))))
+ (funcall fn)))
+
+(defun eat--trace-eshell-adjust-make-process-args (fn &rest args)
+ "Trace `eat--eshell-adjust-make-process-args'.
+
+ARGS is passed to FN, `eat--eshell-adjust-make-process-args', which
+see."
+ (cl-letf*
+ ((command nil)
+ (make-process (symbol-function #'make-process))
+ ((symbol-function #'make-process)
+ (lambda (&rest plist)
+ (prog1
+ (apply make-process plist)
+ (setq command (nthcdr 5 (plist-get plist :command))))))
+ (eat--eshell-setup-proc-and-term
+ (symbol-function #'eat--eshell-setup-proc-and-term))
+ ((symbol-function #'eat--eshell-setup-proc-and-term)
+ (lambda (proc)
+ (let ((time (current-time)))
+ (prog1
+ (funcall eat--eshell-setup-proc-and-term proc)
+ (when (eq (eat-term-parameter
+ eat-terminal 'eat--output-process)
+ proc)
+ (let ((buf (generate-new-buffer
+ (format "*eat-trace %s*: %s"
+ (buffer-name)
+ (mapconcat
+ #'shell-quote-argument
+ command " "))))
+ (width nil)
+ (height nil)
+ (variables nil))
+ (setq-local eat--trace-output-buffer buf)
+ (add-hook 'kill-buffer-hook #'eat--trace-stop nil t)
+ (let ((size (eat-term-size eat-terminal)))
+ (setq width (car size))
+ (setq height (cdr size)))
+ (dolist (var eat--trace-recorded-variables)
+ (push (cons var (symbol-value var)) variables))
+ (with-current-buffer buf
+ (when (fboundp 'lisp-data-mode) (lisp-data-mode))
+ (insert ";; -*- lisp-data -*-\n")
+ (eat--trace-log time 'create 'eshell width height
+ variables)))))))))
+ (apply fn args)))
+
+(defun eat--trace-eshell-output-filter (fn)
+ "Trace `eat--eshell-output-filter'.
+
+FN is the original definition of `eat--eshell-output-filter', which
+see."
+ (if (not (buffer-live-p eat--trace-output-buffer))
+ (funcall fn)
+ (cl-letf* ((eat-term-process-output
+ (symbol-function #'eat-term-process-output))
+ ((symbol-function #'eat-term-process-output)
+ (lambda (terminal output)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'output output))
+ (funcall eat-term-process-output terminal output)))
+ (eat-term-redisplay
+ (symbol-function #'eat-term-redisplay))
+ ((symbol-function #'eat-term-redisplay)
+ (lambda (terminal)
+ (with-current-buffer eat--trace-output-buffer
+ (eat--trace-log nil 'redisplay))
+ (funcall eat-term-redisplay terminal))))
+ (funcall fn))))
+
+(defun eat--trace-eshell-cleanup (fn)
+ "Trace `eat--eshell-cleanup'.
+
+FN is the original definition of `eat--eshell-cleanup', which see."
+ (if (not (buffer-live-p eat--trace-output-buffer))
+ (funcall fn)
+ (cl-letf* ((eat-term-delete (symbol-function #'eat-term-delete))
+ ((symbol-function #'eat-term-delete)
+ (lambda (terminal)
+ (eat--trace-stop)
+ (funcall eat-term-delete terminal))))
+ (funcall fn))))
+
+(define-minor-mode eat-trace-mode
+ "Toggle tracing Eat terminal."
+ :global t
+ :require 'eat
+ :lighter " Eat-Trace"
+ (if eat-trace-mode
+ (progn
+ (advice-add #'eat-exec :around #'eat--trace-exec)
+ (advice-add #'eat--process-output-queue :around
+ #'eat--trace-process-output-queue)
+ (advice-add #'eat--adjust-process-window-size :around
+ #'eat--trace-adjust-process-window-size)
+ (advice-add #'eat--sentinel :around #'eat--trace-sentinel)
+ (advice-add #'eat-reset :around #'eat--trace-reset)
+ (advice-add #'eat--eshell-adjust-make-process-args :around
+ #'eat--trace-eshell-adjust-make-process-args)
+ (advice-add #'eat--eshell-output-filter :around
+ #'eat--trace-eshell-output-filter)
+ (advice-add #'eat--eshell-cleanup :around
+ #'eat--trace-eshell-cleanup))
+ (advice-remove #'eat-exec #'eat--trace-exec)
+ (advice-remove #'eat--process-output-queue
+ #'eat--trace-process-output-queue)
+ (advice-remove #'eat--adjust-process-window-size
+ #'eat--trace-adjust-process-window-size)
+ (advice-remove #'eat--sentinel #'eat--trace-sentinel)
+ (advice-remove #'eat-reset #'eat--trace-reset)
+ (advice-remove #'eat--eshell-adjust-make-process-args
+ #'eat--trace-eshell-adjust-make-process-args)
+ (advice-remove #'eat--eshell-output-filter
+ #'eat--trace-eshell-output-filter)
+ (advice-remove #'eat--eshell-cleanup
+ #'eat--trace-eshell-cleanup)
+ (dolist (buffer (buffer-list))
+ (when (buffer-local-value 'eat--trace-output-buffer buffer)
+ (with-current-buffer buffer
+ (setq-local eat--trace-output-buffer nil))))))
+
+\f
+;;;;; Trace Data Replay.
+
+(defvar eat--trace-replay-buffer nil
+ "The buffer replaying the trace data in current buffer.")
+
+(defvar eat--trace-replay-marker nil
+ "The point from where to read the next sexp.")
+
+(defvar eat--trace-replay-current-sexp-overlay nil
+ "Overlay indicating the current sexp.")
+
+(defvar eat--trace-replay-source-buffer nil
+ "The source buffer containing the trace output.")
+
+(defvar eat--trace-replay-recording-start-time 0.0
+ "Time when recording was started.")
+
+(defvar eat--trace-replay-frame-count 0
+ "The number of the frames in the trace output.")
+
+(defvar eat--trace-replay-progress-frame 0
+ "The number of the frames before the current position.")
+
+(defvar eat--trace-replay-progress nil
+ "The number of seconds of trace output was shown.")
+
+(defun eat--trace-replay-eval (data)
+ "Evalulate DATA as trace output."
+ (let ((inhibit-read-only t))
+ (setq eat--trace-replay-progress
+ (- (car data) eat--trace-replay-recording-start-time))
+ (pcase-exhaustive data
+ (`(,time create ,_ui ,width ,height ,variables)
+ (setq eat--trace-replay-recording-start-time time)
+ (setq eat--trace-replay-progress 0)
+ (dolist (var eat--trace-recorded-variables)
+ (set (make-local-variable var) (alist-get var variables)))
+ (setq eat-terminal (eat-term-make (current-buffer) (point)))
+ (setf (eat-term-parameter eat-terminal 'set-cursor-function)
+ #'eat--set-cursor)
+ (setf (eat-term-parameter eat-terminal 'ring-bell-function)
+ #'eat--bell)
+ (eat-term-resize eat-terminal width height)
+ (eat-term-redisplay eat-terminal))
+ (`(,_time output ,string)
+ (eat-term-process-output eat-terminal string))
+ (`(,_time redisplay)
+ (eat-term-redisplay eat-terminal))
+ (`(,_time resize ,width ,height)
+ (eat-term-resize eat-terminal width height))
+ (`(,_time reset)
+ (eat-term-reset eat-terminal))
+ (`(,_time finish)
+ (eat-term-delete eat-terminal)))
+ (eat--synchronize-scroll (get-buffer-window-list))))
+
+(defun eat--trace-replay-eval-next ()
+ "Evaluate next sexp in trace output."
+ (with-current-buffer eat--trace-replay-source-buffer
+ (goto-char eat--trace-replay-marker)
+ (ignore-error end-of-file
+ (let ((data (read (current-buffer))))
+ (set-marker eat--trace-replay-marker (point))
+ (backward-list)
+ (move-overlay eat--trace-replay-current-sexp-overlay
+ (point) (point))
+ (when-let* ((window (get-buffer-window)))
+ (set-window-point window (point)))
+ (with-current-buffer eat--trace-replay-buffer
+ (cl-incf eat--trace-replay-progress-frame)
+ (eat--trace-replay-eval data))))))
+
+(defun eat-trace-replay ()
+ "Replay terminal according to trace output in current buffer."
+ (interactive)
+ (unless (buffer-live-p eat--trace-replay-buffer)
+ (setq-local eat--trace-replay-buffer
+ (generate-new-buffer
+ (format "*eat-trace-replay*: %s" (buffer-name))))
+ (setq-local eat--trace-replay-marker (point-min-marker))
+ (let ((ov (make-overlay (point-min) (point-min))))
+ (overlay-put ov 'before-string
+ #(" " 0 1 (display (left-fringe right-triangle))))
+ (setq-local eat--trace-replay-current-sexp-overlay ov))
+ (goto-char (point-min))
+ (let ((source (current-buffer))
+ (frame-count 0))
+ (ignore-error end-of-file
+ (while (read (current-buffer))
+ (cl-incf frame-count)))
+ (goto-char (point-min))
+ (with-current-buffer eat--trace-replay-buffer
+ (eat-trace-replay-mode)
+ (setq eat--trace-replay-source-buffer source)
+ (setq eat--trace-replay-frame-count frame-count))))
+ (display-buffer eat--trace-replay-buffer))
+
+(defun eat-trace-replay-next-frame (&optional n)
+ "Show the Nth next frame.
+
+N defaults to 1. Interactively, N is the prefix argument."
+ (interactive "p")
+ (dotimes (_ n)
+ (eat--trace-replay-eval-next)))
+
+(defun eat-trace--cleanup ()
+ "Clean up the source buffer before the terminal being killed."
+ (when (buffer-live-p eat--trace-replay-source-buffer)
+ (with-current-buffer eat--trace-replay-source-buffer
+ (setq eat--trace-replay-buffer nil)
+ (setq eat--trace-replay-marker nil)
+ (delete-overlay eat--trace-replay-current-sexp-overlay))))
+
+(defvar eat-trace-replay-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "n") #'eat-trace-replay-next-frame)
+ (define-key map (kbd "<down>") #'eat-trace-replay-next-frame)
+ (define-key map (kbd "q") #'quit-window)
+ map)
+ "Keymap for Eat-Trace-Replay mode.")
+
+(define-derived-mode eat-trace-replay-mode special-mode
+ "Eat-Trace-Replay"
+ "Major mode for replaying terminal according to trace output."
+ (mapc #'make-local-variable '(eat-terminal
+ eat--trace-replay-source-buffer
+ eat--trace-replay-recording-start-time
+ eat--trace-replay-progress
+ eat--trace-replay-frame-count
+ eat--trace-replay-progress-frame))
+ (setq-local
+ mode-line-process
+ '("[" (:eval (number-to-string eat--trace-replay-progress-frame))
+ "/" (:eval (number-to-string eat--trace-replay-frame-count))
+ "]"))
+ (add-hook 'kill-buffer-hook #'eat-trace--cleanup nil t))
+
+\f
+;;;; Miscellaneous.
+
+(defun eat-compile-terminfo ()
+ "Compile terminfo databases of Eat."
+ (interactive)
+ ;; Check for required files and programs.
+ (let ((source-path (expand-file-name "eat.ti" eat--install-path))
+ (tic-path (executable-find "tic")))
+ (unless (file-exists-p source-path)
+ (error "Eat not installed properly: %s"
+ "Terminfo source file not found"))
+ (unless tic-path
+ (error "Terminfo compiler `tic' not found"))
+ (message "Compiling terminfo databases...")
+ ;; Compile.
+ (let* ((command (format "env TERMINFO=\"%s\" %s -x %s"
+ eat-term-terminfo-directory tic-path
+ source-path))
+ (status
+ (with-temp-buffer
+ (make-directory eat-term-terminfo-directory 'parents)
+ (let ((proc (start-process-shell-command
+ "eat-terminfo-compile"
+ (current-buffer) command)))
+ (while (process-live-p proc)
+ (sleep-for 0.02))
+ (process-exit-status proc)))))
+ (if (= status 0)
+ (message "Compiling terminfo databases...done")
+ (message "Compiling terminfo databases...error")
+ (error "Command `%s' exited with non-zero exit code %i"
+ command status)))))
+
+\f
+;;;; Footer.
+
+(defun eat-reload ()
+ "Reload Eat."
+ (interactive)
+ (unless eat--being-loaded
+ ;; Remove .elc suffix to load native compiled version if possible.
+ (load (string-remove-suffix ".elc" eat--load-file-path))))
+
+(setq eat--being-loaded nil)
+
+(provide 'eat)
+;;; eat.el ends here
--- /dev/null
+This is docQL52HQ.info, produced by makeinfo version 6.8 from eat.texi.
+
+This manual is for Eat (version 0.9.4, 15 December 2023), a terminal
+emulator for Emacs.
+
+ Copyright © 2022, 2023 Akib Azmain Turja.
+
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU Free Documentation License,
+ Version 1.3 or any later version published by the Free Software
+ Foundation; with no Invariant Sections, no Front-Cover Texts, and
+ no Back-Cover Texts. A copy of the license is included in the
+ section entitled “GNU Free Documentation License”.
+INFO-DIR-SECTION Emacs
+START-INFO-DIR-ENTRY
+* Eat: (eat). Emulate A Terminal.
+END-INFO-DIR-ENTRY
+
+\1f
+File: docQL52HQ.info, Node: Top, Next: Intro, Up: (dir)
+
+Eat Manual
+**********
+
+This manual is for Eat (version 0.9.4, 15 December 2023), a terminal
+emulator for Emacs.
+
+ Copyright © 2022, 2023 Akib Azmain Turja.
+
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU Free Documentation License,
+ Version 1.3 or any later version published by the Free Software
+ Foundation; with no Invariant Sections, no Front-Cover Texts, and
+ no Back-Cover Texts. A copy of the license is included in the
+ section entitled “GNU Free Documentation License”.
+
+* Menu:
+
+Introduction
+* Intro:: What is Eat?
+* Hello Terminal:: Starting Eat’s terminal for the first time.
+* Project-local Terminal:: One project, one terminal.
+* Eshell Terminal:: Eat’s terminal emulation in Eshell.
+
+Basic Operations
+* Keyboard:: Most keyboard keys are captured by Eat.
+* Mouse:: Eat supports mouse.
+* Input Modes:: Input modes for various use-cases.
+* Password Input:: Safely inputting credentials.
+
+Advanced Customizations
+* Shell Integration:: Getting the most from Eat and your shell.
+* Querying Before Kill:: Confirming before you kill your terminal.
+* Display:: The region where everything is shown.
+* Scrollback:: Region for things that went out of display.
+* Cursor Types:: Cursor can displayed in many forms.
+* Mouse Tracking:: Eat tracks mouse, but this can be changed.
+* Clipboard:: Integrating kill ring with terminal.
+* Colors:: Eat can show more than sixteen million colors.
+* Fonts:: Eat can show up to sixteen different fonts.
+* Blinking Text:: Annoying blinking texts.
+* Performance Tuning:: Fine tuning to maximize performance.
+
+Recovering from Problems
+* Common Problems:: Common problem, and fixes.
+* Reporting Bugs:: How to report problems?
+* Tracing the Terminal:: Gathering some crucial information to
+ reproduce a bug.
+
+Appendices
+* GNU General Public License:: Copying condition for Eat.
+* GNU Free Documentation License:: Copying conditions of this manual.
+* Index:: A list of various things.
+
+\1f
+File: docQL52HQ.info, Node: Intro, Next: Hello Terminal, Prev: Top, Up: Top
+
+1 Introduction
+**************
+
+Eat (Emulate A Terminal) is a terminal emulator for Emacs. It emulates
+a XTerm-like terminal, just like many other terminal emulators. But it
+has some key features that make Eat distinct from other terminal
+emulators.
+
+ Firstly, it’s in Emacs, which means you don’t need to leave the
+comfort of Emacs to use terminal.
+
+ Secondly, it’s easy and convenient to use. It is tries to stay out
+of your way, allowing you to maximize your productivity.
+
+ Finally, special care has been taken while designing the keybindings,
+so that the terminal doesn’t conflict with Emacs default keybindings on
+both graphical display and text display, while still allowing you to run
+full screen programs like Emacs within the terminal.
+
+\1f
+File: docQL52HQ.info, Node: Hello Terminal, Next: Project-local Terminal, Prev: Intro, Up: Top
+
+2 Hello Terminal
+****************
+
+The terminal can be started with ‘M-x eat’. It’ll create a terminal and
+run the default shell (*note (emacs)Interactive Shell::) in it. You
+should get a shell prompt and be able to write shell commands and
+execute them. Full screen programs like ‘htop’, ‘lynx’ and Emacs will
+work inside it, just like any other terminal. (If the terminal doesn’t
+work as expected, *note Common Problems::.)
+
+ If an Eat terminal already exists, ‘M-x eat’ will switch to it. To
+create a new terminal, call it with a prefix argument like this, ‘C-u
+M-x eat’.
+
+ If you give it a numeric prefix argument N, for example ‘C-u 42 M-x
+eat’, it’ll switch to a terminal in the buffer ‘*eat*<N>’, ‘*eat*<42>’
+for example, or it’ll create a new terminal if that buffer doesn’t
+exist.
+
+ If you give it double prefix argument, for example ‘C-u C-u M-x eat’,
+you’ll be prompted for the program or shell command to run, and it’ll be
+run in a newly created terminal.
+
+\1f
+File: docQL52HQ.info, Node: Project-local Terminal, Next: Eshell Terminal, Prev: Hello Terminal, Up: Top
+
+3 Project-local Terminal
+************************
+
+Usually, you don’t use a single terminal for everything, instead you
+open a terminal for each project that needs it. So there is command
+named ‘eat-project’. It opens a new terminal in project root directory,
+or switches to a already existing project terminal. It too accepts
+prefix argument, just like the ordinary ‘eat’ command.
+
+\1f
+File: docQL52HQ.info, Node: Eshell Terminal, Next: Keyboard, Prev: Project-local Terminal, Up: Top
+
+4 Eshell Terminal Emulation
+***************************
+
+Eat also supports terminal emulation outside Eat’s terminal. So you can
+emulate terminal in Eshell (*note (eshell)Top::) with Eat. After
+configuring Eshell to use Eat for terminal emulation, you can run any
+full screen terminal program in Eshell.
+
+ To enable terminal emulation in Eshell, enable the global minor mode
+‘eat-eshell-mode’. It will enable Eat’s terminal emulation in Eshell.
+To disable the terminal emulation, disable the minor mode.
+
+ You can’t toggle the global minor mode while any Eshell command is
+running, so terminate any Eshell command or wait them to finish before
+toggling the mode.
+
+ Unless stated otherwise, everything described in this manual about
+Eat terminal also applies to Eshell terminal emulation.
+
+ You might also want to set ‘eshell-visual-commands’ user option to
+nil, since they’ll work in Eshell when ‘eat-eshell-mode’ is enabled.
+
+ If you want to run Eshell visual commands with Eat, you can enable
+the global minor mode ‘eat-eshell-visual-command-mode’.
+
+\1f
+File: docQL52HQ.info, Node: Keyboard, Next: Mouse, Prev: Eshell Terminal, Up: Top
+
+5 Keyboard
+**********
+
+Just like any other text terminal, the primary interaction device with
+Eat terminal is the keyboard. Eat forwards all supported keyboard
+events like ‘a’, ‘E’, ‘RET’, ‘C-a’ to the terminal.
+
+ However, this conflict with Emacs keybinding conventions, and makes
+it almost impossible to call any other Emacs command. So, by default,
+Eat doesn’t intercept the key sequences beginning with the following
+keys and lets Emacs to handle them: ‘C-\’, ‘C-c’, ‘C-x’, ‘C-g’, ‘C-h’,
+‘C-M-c’, ‘C-u’, ‘C-q’, ‘M-x’, ‘M-:’, ‘M-!’ and ‘M-&’.
+
+ To input the above key sequences, prefix them with ‘C-q’. ‘C-q’
+reads the next event and sends to directly to the terminal. For
+example, to input ‘M-:’, use the key sequence ‘C-q M-:’.
+
+ For an alternative way to input these exceptional characters, *note
+Char Mode::.
+
+\1f
+File: docQL52HQ.info, Node: Mouse, Next: Input Modes, Prev: Keyboard, Up: Top
+
+6 Mouse
+*******
+
+Eat supports mouse tracking. That means in programs like Emacs, ‘htop’,
+etc, that support mouse, you can hover and click on text and buttons.
+You can also use your mouse wheel to scroll text, if the program
+supports it.
+
+ *Note Mouse Tracking:: to configure mouse tracking.
+
+\1f
+File: docQL52HQ.info, Node: Input Modes, Next: Password Input, Prev: Mouse, Up: Top
+
+7 Input Modes
+*************
+
+By default, Eat forwards all supported keys to terminals, except some
+exceptions. It is possible to input them with ‘C-q’, but it is not very
+convenient.
+
+ To conveniently input those character, they should be bound to input
+themselves to the terminal (i.e. pressing ‘M-x’ will input ‘M-x’,
+bypassing Emacs). But this is conflicts with Emacs’s default
+keybindings, so this can’t done, at least by default.
+
+ To overcome the problem, Eat implements several “input modes”. Each
+input mode has a different set of keybindings for different
+applications.
+
+7.1 Semi-char Mode
+==================
+
+“Semi-char mode” is the default input mode of Eat. This works for most
+inputs. It forwards all keys, except ‘C-\’, ‘C-c’, ‘C-x’, ‘C-g’, ‘C-h’,
+‘C-M-c’, ‘C-u’, ‘M-x’, ‘C-q’, ‘M-:’, ‘M-!’, ‘M-&’ and some other keys,
+Emacs handles them.
+
+ To input these exceptions, there is a key ‘C-q’. This reads the next
+input event and sends that as the input. For example, the key sequences
+‘C-q M-:’ inputs ‘M-:’, ‘C-q C-g’ inputs ‘C-g’.
+
+ Input methods (*note (emacs)Input Methods::) work in this mode, so,
+unlike Term (*note Emacs Terminal Emulator: (emacs)Terminal emulator.),
+Emacs built-in terminal emulator, you can still input any character.
+
+ In “semi-char mode”, ‘C-c C-c’ sends a ‘C-c’, just for convenience,
+and ‘C-c C-k’ kills the terminal program.
+
+ You can customize the exceptions by customizing the user option
+‘eat-semi-char-non-bound-keys’, and
+‘eat-eshell-semi-char-non-bound-keys’ for Eshell integration. Both user
+options contain a list of keys of form ‘[KEY]’, where KEY is a key not
+to bind. KEY mustn’t contain meta modifier. To not bind a key with
+meta modifier, use a vector of form ‘[?\e KEY]’, where KEY is the key
+without meta modifier. These user options contain all the “semi-char”
+mode exceptions listed above, plus some more exceptions.
+
+ If you set the user options manually (for example, with ‘setq’), you
+must call ‘eat-update-semi-char-mode-map’ or
+‘eat-eshell-update-semi-char-mode-map’ respectively, and finally reload
+Eat (you can do this with the command ‘eat-reload’). Or alternatively
+you can set the user options before Eat is loaded.
+
+7.2 Char Mode
+=============
+
+By default, Eat is in “semi-char mode”. In this input mode, Eat
+forwards all supported keys to terminals, except some exceptions, *note
+Semi-char Mode::. It is possible to input them with ‘C-q’, but it is
+not very convenient.
+
+ To overcome this problem, Eat implements another input mode called
+“char mode”. To switch to “char mode”, press ‘C-c M-d’ in “semi-char
+mode”. In Eshell, the command ‘eshell-toggle-direct-send’ is remapped
+to enable “char-mode”, which is usually bound to ‘C-c M-d’.
+
+ In this input mode, Eat forwards all supported keys. However, input
+methods still work in this mode, so you can still input keys that are
+not on your keyboard.
+
+ To get out of “char mode”, press ‘C-M-m’ or ‘M-<RET>’, this switches
+back to “semi-char mode”.
+
+7.3 Emacs Mode
+==============
+
+In “emacs mode”, no input events are send to the terminal. In this
+mode, you can interact with the terminal buffer just like a regular
+buffer. However, you are not allowed to change the buffer contents.
+
+ To switch to “emacs mode”, press ‘C-c C-e’ from “semi-char mode”.
+
+ In this mode, ‘C-c C-k’ kills the terminal program like in “semi-char
+mode”.
+
+ From “emacs mode”, you can switch to “semi-char mode” with ‘C-c C-j’
+and to “char mode” with ‘C-c M-d’. In Eshell, the command
+‘eshell-toggle-direct-send’ is remapped to enable “char-mode”, which is
+usually bound to ‘C-c M-d’.
+
+7.4 Line Mode
+=============
+
+In “line mode”, input is sent one line at a line, similar to Comint or
+Shell mode (*note (emacs)Interactive Shell::). Like “emacs mode”, you
+can interact with buffer as you wish; but at the very end of the buffer,
+you can edit the input line with usual Emacs commands. This is not
+available in Eshell.
+
+ To enter “line mode”, press ‘C-c C-l’ from “semi-char mode” or “emacs
+mode”.
+
+ ‘<RET>’ sends the current input with a trailing newline, and clear
+the input area for new input to be written. When called with a prefix
+argument, no newline is appended before sending input. To input a
+newline character without actually sending it, you can press ‘C-c
+<SPC>’.
+
+ ‘C-c C-c’ discards the input completely and sends an interrupt to the
+terminal. ‘C-d’ deletes the character after the point, or sends EOF if
+the input is empty.
+
+ You can’t modify the terminal in “line mode”, you can write only in
+the input line. Eat automatically moves the point to the input line if
+you try to insert character in the terminal region. This behavior can
+be disabled by customizing ‘eat-line-auto-move-to-input’ to ‘nil’.
+
+ You can exit to “emacs mode”, “semi-char mode” or “char mode” with
+‘C-c C-e’, ‘C-c C-j’ or ‘C-c M-d’ respectively. If there’s any pending
+input when exiting line mode, it is sent as is to the terminal.
+
+ The input history is recorded. You can cycle through the history
+with ‘M-p’ and ‘M-n’, and also with ‘C-<up>’ and ‘C-<down>’. ‘C-c M-r’
+and ‘C-c M-s’ searches the input history taking the current input as the
+query. ‘C-c M-r’ searches backward while ‘C-c M-s’ searches forward.
+And ‘C-c C-r’ searches the input history using minibuffer with
+completion, useful specially if you use any minibuffer completion
+UI/framework.
+
+ You can also use Isearch (*note (emacs)Incremental Search::) to
+search through the input history, with ‘M-r’. You can also customize
+‘eat-line-input-history-isearch’ to use all standard Isearch commands to
+search the input history.
+
+ -- User Option: eat-line-input-history-isearch
+ Controls where Isearch searches in Eat buffer. If ‘t’, usual
+ Isearch commands in Eat buffer search in the input history. If
+ ‘dwim’, Isearch keys search in the input history only when initial
+ point position is on input line. When starting Isearch from other
+ parts of the Eat buffer, they search in the Eat buffer. If ‘nil’,
+ Isearch operates on the whole Eat buffer.
+
+ Input history is not loaded from the shell history file, to do that,
+*Note Line Mode Integration::.
+
+\1f
+File: docQL52HQ.info, Node: Password Input, Next: Shell Integration, Prev: Input Modes, Up: Top
+
+8 Password Input
+****************
+
+By default, every keystroke gets recorded in the lossage, which can be
+seen by pressing ‘C-h l’. This is actually a good thing, unless you’re
+inputting password.
+
+ Emacs doesn’t record keystrokes when a password is read from the
+minibuffer. However, when the password prompt is in the terminal, the
+keys you use to type in your password gets recorded. To prevent this
+from happening, you can use the command ‘eat-send-command’, it’ll read
+password from the minibuffer and send it. Since the password is read
+from the minibuffer, it’s not recorded.
+
+\1f
+File: docQL52HQ.info, Node: Shell Integration, Next: Querying Before Kill, Prev: Password Input, Up: Top
+
+9 Shell Integration
+*******************
+
+Eat comes with shell scripts to integrate your favorite shell with Eat.
+When shell integration is enabled and the script is loaded in your
+shell, it’ll take care of everything and provide many useful features.
+
+ Currently only GNU Bash and Zsh are supported.
+
+ If you use GNU Bash, put the following in your ‘.bashrc’ file:
+
+ [ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
+ source "$EAT_SHELL_INTEGRATION_DIR/bash"
+
+ If you use Zsh, put the following in your ‘.zshrc’ file:
+
+ [ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
+ source "$EAT_SHELL_INTEGRATION_DIR/zsh"
+
+9.1 Directory tracking
+======================
+
+After you’ve setup shell integration, the Eat will track the working
+directory of your shell. That means ‘find-file’ will start from your
+shell’s current working directory. This also works in Eshell, but after
+the program exits, the current working directory is changed back to the
+directory from where the program was invoked.
+
+ -- User Option: eat-enable-directory-tracking
+ This controls directory tracking. When set to non-‘nil’, Eat
+ tracks the current working directory of programs.
+
+9.2 Shell Prompt Navigation
+===========================
+
+You can navigate shell prompts in “emacs” and “semi-char” mode. ‘C-c
+C-p’, bound to ‘eat-previous-shell-prompt’, goes to the previous shell
+prompt. ‘C-c C-n’, bound to ‘eat-next-shell-prompt’, is the opposite,
+it goes to the next shell prompt. This doesn’t work in Eshell.
+
+ You can narrow (*note (emacs)Narrowing::) down Eat buffer to a shell
+prompt and its output (if any) using the key sequence ‘C-x n d’, bound
+to ‘eat-narrow-to-shell-prompt’.
+
+9.3 Shell Prompt Annotation
+===========================
+
+When shell integration is setup, Eat annotates each shell prompt. Eat
+puts a mark on the shell prompt indicating the whether the command
+entered in that prompt is running, exited successfully or exited with
+non-zero status. This doesn’t work in Eshell. You can disable this
+feature if you want.
+
+ -- User Option: eat-enable-shell-prompt-annotation
+ This controls shell prompt annotation by Eat. When set to
+ non-‘nil’, Eat annotates shell prompts to indicate the status of
+ the command entered in that prompt.
+
+ Eat uses the marginal area (*note (elisp)Display Margins::) on the
+left side to display the annotation. You also use the right margin.
+
+ -- User Option: eat-shell-prompt-annotation-position
+ This controls where the shell prompt annotations are displayed.
+ When set to ‘left-margin’ (the default), Eat uses the left margin.
+ When set to ‘right-margin’, Eat uses the right margin.
+
+ Eat uses the strings “-”, “0” and “X” respectively to indicate the
+command is running, the command has succeeded and the command has
+failed. You can also customize the them. The user option
+‘eat-shell-prompt-annotation-running-margin-indicator’ and the face
+‘eat-shell-prompt-annotation-running’ control the indicator used to
+indicate the command is running. The user option
+‘eat-shell-prompt-annotation-success-margin-indicator’ and the face
+‘eat-shell-prompt-annotation-success’ control the indicator used to
+indicate the command has exited successfully. And finally the user
+option ‘eat-shell-prompt-annotation-failure-margin-indicator’ and the
+face ‘eat-shell-prompt-annotation-failure’ control the indicator used to
+indicate the command has exited unsuccessfully with non-zero exit
+status.
+
+9.4 Message Passing
+===================
+
+After enabling shell integration, you can send messages to Emacs from
+your shell. Then you can handle the message on Emacs side using usual
+Emacs Lisp function.
+
+ When shell integration script is loaded, a function named ‘_eat_msg’
+is defined in your shell. You can use this to send any message to
+Emacs. (The ‘_’ in the beginning of the function name is intentional to
+prevent shadowing any actual command.)
+
+ -- Command: _eat_msg HANDLER-NAME MESSAGE...
+ Send message MESSAGE, handled by the handler named HANDLER-NAME in
+ Emacs.
+
+ The messages are handled with the handlers defined in
+‘eat-message-handler-alist’.
+
+ -- User Option: eat-message-handler-alist
+ Alist of message handler name and its handler function. The keys
+ are the names of message handlers (i.e. the HANDLER-NAME argument
+ of ‘_eat_msg’), and the values are their respective handler
+ functions. The handler function is called with the MESSAGE
+ arguments of ‘_eat_msg’. Messages with undefined handlers are
+ ignored. To disable message passing, set this to nil.
+
+ Beware, messages can be sent by malicious and/or buggy programs
+running in the shell, therefore you should always verify the message
+before doing anywhere.
+
+9.5 Line Mode Integration
+=========================
+
+When shell integration is enabled, the input history of line mode is
+automatically filled with the shell history when the shell starts. Also
+you can make Eat automatically switch to “line mode” (*note Line Mode::)
+for you when the shell prompt appears.
+
+ -- User Option: eat-enable-auto-line-mode
+ When non-nil, automatically switch to line mode the shell prompt
+ appears.
+
+\1f
+File: docQL52HQ.info, Node: Querying Before Kill, Next: Display, Prev: Shell Integration, Up: Top
+
+10 Querying Before Kill
+***********************
+
+When a terminal is killed, the terminal process is also killed. Since
+the process can do some important things, Eat asks for confirmation
+before killing a terminal with running process by default. Eat provides
+the user option ‘eat-query-before-killing-running-terminal’ to control
+this.
+
+ -- User Option: eat-query-before-killing-running-terminal
+ When set to ‘nil’, Eat would never ask. When set to ‘t’, Eat would
+ always ask for confirmation. When set to ‘auto’, Eat would ask
+ only if a shell command is running inside the shell running in the
+ terminal. This is effective only after shell integration is
+ enabled in the shell (*note Shell Integration::) (i.e. after the
+ shell integration code is executed on shell); before that it is
+ essentially same as ‘t’, and Eat will always query.
+
+\1f
+File: docQL52HQ.info, Node: Display, Next: Scrollback, Prev: Querying Before Kill, Up: Top
+
+11 Display
+**********
+
+Display is the region you see on the terminal. The program writes to
+the display and manipulates the text on the display. The display can be
+of any size. The cursor is always on the display (though it might be
+invisible sometimes, *note Cursor Types::).
+
+ You can resize the display by resizing the terminal window. The
+display size is controlled by the Emacs user option
+‘window-adjust-process-window-size-function’. *Note (elisp)Process
+Buffers:: for the possible values of the user option.
+
+\1f
+File: docQL52HQ.info, Node: Scrollback, Next: Cursor Types, Prev: Display, Up: Top
+
+12 Scrollback
+*************
+
+When you go too downward on the terminal, the terminal starts to
+“scroll”. This causes the line at the upper side of the terminal to go
+out of the display and become hidden. But these line are not deleted,
+they are just put in the scrollback region.
+
+ Scrollback region is a region just above the display of the terminal.
+This contains the lines that went out of display due to scrolling up.
+
+ Scrollback region is not unlimited by default, to avoid using too
+much memory. You can change the limit, or remove it altogether.
+
+ -- User Option: eat-term-scrollback-size
+ This controls the size of scrollback region. It is expressed in
+ character. If set to SIZE, Eat won’t store more than SIZE
+ characters in the scrollback region. If set to ‘nil’, the
+ scrollback region is unlimited.
+
+\1f
+File: docQL52HQ.info, Node: Cursor Types, Next: Mouse Tracking, Prev: Scrollback, Up: Top
+
+13 Cursor Types
+***************
+
+In terminal, cursor can be of up to three type: “visible”, “invisible”
+and “very visible”. “Visible” is the default cursor type, which is the
+cursor you usually see in a shell (unless the shell changes the cursor
+type). “Invisible” is, as the name suggests, invisible, you can’t see
+it. “Very visible” cursor is a blinking cursor, programs use this to
+help you not lose the cursor.
+
+ The cursor type can customized with three user options for the three
+types of cursor. Each of the user options share the same format.
+
+ -- User Option: eat-default-cursor-type
+ This controls the cursor shape of the “visible” cursor type.
+
+ -- User Option: eat-invisible-cursor-type
+ This controls the cursor shape of the “invisible” cursor type.
+
+ -- User Option: eat-very-visible-cursor-type
+ This controls the cursor shape of the “very visible” cursor type.
+ This cursor blinks, switching between the default cursor shape and
+ a hollow box.
+
+ -- User Option: eat-vertical-bar-cursor-type
+ This controls the cursor shape of the “vertical bar” cursor type.
+
+ -- User Option: eat-very-visible-vertical-bar-cursor-type
+ This controls the cursor shape of the “very visible vertical bar”
+ cursor type. This cursor blinks.
+
+ -- User Option: eat-horizontal-bar-cursor-type
+ This controls the cursor shape of the “horizontal bar” cursor type.
+
+ -- User Option: eat-very-visible-horizontal-bar-cursor-type
+ This controls the cursor shape of the “very visible horizontal bar”
+ cursor type. This cursor blinks.
+
+ The value type of all these user options is a list. The list is of
+form (CURSOR-ON BLINKING-FREQUENCY CURSOR-OFF). BLINKING-FREQUENCY is
+the frequency of blinking of cursor. It is a number, controlling how
+many times the cursor will blink a second. This can also be ‘nil’, this
+will disable cursor blinking. CURSOR-ON is the default cursor shape,
+only this shape is shown on the display when blinking is disabled. This
+uses the same format as Emacs’s ‘cursor-type’ user option (*note
+(emacs)Cursor Display::). When BLINKING-FREQUENCY is a number, Eat will
+consult to the third element of the list, CURSOR-OFF, whose format same
+as CURSOR-ON. The blinking cursor switches between CURSOR-ON and
+CURSOR-OFF cursor shape.
+
+\1f
+File: docQL52HQ.info, Node: Mouse Tracking, Next: Clipboard, Prev: Cursor Types, Up: Top
+
+14 Mouse Tracking
+*****************
+
+Eat tracks mouse by default, when the program supports mouse. But
+sometimes, you may want to avoid using mouse, or you might not have a
+mouse at all. So mouse tracking can be toggled.
+
+ -- User Option: eat-enable-mouse
+ This user option controls mouse tracking. When set to non-‘nil’,
+ mouse tracking is enabled. Set to this to ‘nil’ to disable mouse
+ tracking. This is enabled by default.
+
+\1f
+File: docQL52HQ.info, Node: Clipboard, Next: Colors, Prev: Mouse Tracking, Up: Top
+
+15 Clipboard
+************
+
+Just like any other buffer, you can yank text in terminal with ‘C-y’
+(bound to ‘eat-yank’) or ‘M-y’ (bound to ‘eat-yank-pop’) in “semi-char
+mode”.
+
+ Programs can also request to the terminal to kill (*note
+(emacs)Killing::) something. It is up to Eat whether the request will
+be fulfilled or not. By default, Eat fulfills the request and kills the
+text. This can sometimes be annoying, when the program automatically
+kills text without user interaction. This killing can be configured
+with the following user option:
+
+ -- User Option: eat-enable-kill-from-terminal
+ This controls killing texts from terminal. When set to non-‘nil’,
+ killing something from terminal add the text to Emacs’s kill ring
+ (*note (emacs)Kill Ring::). This is enabled by default.
+
+ Programs can also request the text in kill ring. Again, this is up
+to Eat whether the request will be fulfilled or not. You can customize
+the following user option to configure this:
+
+ -- User Option: eat-enable-yank-to-terminal
+ This controls sending kill ring texts to terminal. When set to
+ non-‘nil’, programs can receive the kill ring contents. This is
+ disabled by default for security reasons.
+
+\1f
+File: docQL52HQ.info, Node: Colors, Next: Fonts, Prev: Clipboard, Up: Top
+
+16 Colors
+*********
+
+Eat can show more than 16 million colors (16,777,216 colors exactly).
+Eat has also a palette of 256 colors, which is more than enough for most
+applications. Programs usually use this color palette. Each of these
+256 colors can customized.
+
+ There are 256 faces for the 256 colors, one face for each color.
+They are named like ‘eat-term-color-N’, which corresponds to color N,
+and N can be any number between 0 and 255 (inclusive). For example,
+color 42 is can be changed by customizing ‘eat-term-color-42’.
+
+ The foreground attribute contains the color value to use for the
+corresponding color. Other attributes are currently ignored and
+reserved for future changes.
+
+ Each of the first 16 colors, from ‘eat-term-color-0’ to
+‘eat-term-color-15’ also have a alias. They are respectively
+‘eat-term-color-black’, ‘eat-term-color-red’, ‘eat-term-color-green’,
+‘eat-term-color-yellow’, ‘eat-term-color-blue’,
+‘eat-term-color-magenta’, ‘eat-term-color-cyan’, ‘eat-term-color-white’,
+‘eat-term-color-bright-black’, ‘eat-term-color-bright-red’,
+‘eat-term-color-bright-green’, ‘eat-term-color-bright-yellow’,
+‘eat-term-color-bright-blue’, ‘eat-term-color-bright-magenta’,
+‘eat-term-color-bright-cyan’ and ‘eat-term-color-bright-white’.
+
+ Eat also supports 24-bit colors, or so called “truecolor”. Programs
+like Emacs can give a RGB triplet to use as the color of some text. As
+the programs directly specify the color in this case, you can’t
+customize these color. But you may configure the program sending the
+color codes.
+
+ Eat doesn’t always advertise color support depending on the display
+Eat is running. For example, if you are on a Linux console which
+supports only eight colors, Eat will advertise eight color support to
+the programs, while on graphical displays with 24-bit color support, Eat
+will report 24-bit color support. This is because Eat supports more
+colors, the display doesn’t always support them.
+
+ Eat does the trick by setting the ‘TERM’ environment variable of the
+program. The value of ‘TERM’ depends on the number of the available
+colors on the display. This environment variable is controlled by the
+following user option:
+
+ -- User Option: eat-term-name
+ The value of ‘TERM’ environment variable as a string. The value
+ can also be a function taking no arguments, that function should
+ return a string which used as the value of ‘TERM’. The default
+ value is ‘eat-term-get-suitable-term-name’, which is responsible
+ for the behavior described above.
+
+\1f
+File: docQL52HQ.info, Node: Fonts, Next: Sixel, Prev: Colors, Up: Top
+
+17 Fonts
+********
+
+Programs may request the terminal to change the text font. It can
+change text weight, use italic text, or even change the font family
+altogether.
+
+ Programs may request the terminal to show some text bolder than
+normal. Bold text uses the face ‘eat-term-bold’.
+
+ Programs may also request the terminal to show some text fainter than
+normal. Faint text uses the face ‘eat-term-faint’.
+
+ Programs may request the terminal to show italic text too. Italic
+text uses the customizable face ‘eat-term-italic’.
+
+ The number of available fonts is ten. Most of the programs doesn’t
+change the font. Following many other terminal emulator, Eat actually
+uses the same font, the default font, regardless of the font requested
+by the program, by default.
+
+ There are ten faces for ten fonts, one face for each. They are named
+like ‘eat-term-font-N’, which corresponds to color N, and N can be any
+number between 0 and 9 (inclusive). For example, the font 6 is can be
+changed by customizing ‘eat-term-font-6’. Font 0 is the default font.
+
+\1f
+File: docQL52HQ.info, Node: Sixel, Next: Blinking Text, Prev: Fonts, Up: Top
+
+18 Sixel
+********
+
+Eat can show Sixel graphics. Sixel is a bitmap graphics format that can
+be used to display graphics in a terminal, for example, images, or
+plotting graphs.
+
+ You can control the display of Sixel images by customizing the
+following user options.
+
+ -- User Option: eat-sixel-scale
+ This is a non-negative number that specifies the amount to scale
+ the image by.
+
+ -- User Option: eat-sixel-aspect-ratio
+ This is a non-negative number that specifies the aspect ratio, i.e.
+ the ratio of width and height of a Sixel pixel. For example, the
+ value of 2 means the width of a Sixel pixel is the double of its
+ height.
+
+ Eat converts Sixel graphics to an image format Emacs can natively
+display. This preference of image formats can be configured by
+customizing the ‘eat-sixel-render-formats’ user option.
+
+ -- User Option: eat-sixel-render-formats
+ List of formats to render Sixel, in order of preference. Each
+ element of the list is one of ‘xpm’, ‘svg’, ‘half-block’,
+ ‘background’, ‘none’. ‘xpm’ and ‘svg’ means to use XPM and SVG
+ image format respectively, ‘half-block’ means to use UTF-8 half
+ block characters, ‘background’ means to just use background color,
+ and ‘none’ means to not render the image, instead just clear the
+ area.
+
+\1f
+File: docQL52HQ.info, Node: Blinking Text, Next: Performance Tuning, Prev: Sixel, Up: Top
+
+19 Blinking Text
+****************
+
+Programs can request the terminal to blink some text. This helps to get
+user attention. But however, often this annoying to many people and
+also has accessiblity problems. So this is disabled by default.
+
+ -- User Option: eat-enable-blinking-text
+ This controls the blinking of text with blink attribute. When set
+ to non-‘nil’, Eat arranges that text with blink attribute will
+ blink at a certain interval.
+
+ You can toggle blinking temporarily by toggle the buffer-local minor
+mode ‘eat-blink-mode’. This is only effective in the buffer where the
+mode is toggled.
+
+ By default, ‘eat-enable-blinking-text’ is set to ‘nil’. This
+disables text blinking and causes the text with blink attribute to be
+displayed in inverse video (swapped foreground and background).
+
+ Programs may also request to blink some text more rapidly that other
+blinking text. When blinking is disabled, the face
+‘eat-term-slow-blink’ is used for slowly blinking text, and
+‘eat-term-fast-blink’ for rapidly blinking text.
+
+ When blinking is enabled, by setting ‘eat-enable-blinking-text’ to
+non-‘nil’ value, the following user options can be customized to change
+the rate of blinking:
+
+ -- User Option: eat-slow-blink-frequency
+ The blinking rate of slowly blinking text. When set to a number N,
+ it causes slowly blinking text to blink N times a second. The
+ value can also be a floating point number. The default value is 2,
+ meaning that the slowing text will blink two times a second.
+
+ -- User Option: eat-fast-blink-frequency
+ The blinking rate of rapidly blinking text. When set to a number
+ N, it causes rapidly blinking text to blink N times a second. The
+ value can also be a floating point number as well. The default
+ value is 3, meaning that the slowing text will blink three times a
+ second.
+
+\1f
+File: docQL52HQ.info, Node: Performance Tuning, Next: Common Problems, Prev: Blinking Text, Up: Top
+
+20 Performance Tuning
+*********************
+
+Eat tries to be as fast as possible. So Eat employs some techniques to
+maximize performance.
+
+ Some program choke and hang when given too much input at once. So
+Eat divides large input to smaller chunks and sends the chunks one at a
+time. The maximum size of a input chunk is controlled by
+‘eat-input-chunk-size’.
+
+ -- User Option: eat-input-chunk-size
+ The value is a integer. Eat treat input larger than this many
+ character as large and breaks it into chunks of at most this size
+ before sending the input.
+
+ Programs also break large output into smaller chunks before sending
+it to the terminal, for same reason. Eat doesn’t suffer from the
+problem, but there isn’t any standard way to inform programs about this,
+and usually there are other obstructions sending large amount of data at
+once. These small chunks create another problem for Eat, flickering.
+When updating the whole display, the output is usually pretty large and
+the programs break them into smaller chunks. Each of the chunks update
+the display partially. After receiving the last chunk, the update is
+complete and the display can be updated. But it is impossible for Eat
+to guess the last chunk, so Eat has to redisplay or update the display
+after receiving each chunk. This is the reason why sometimes the
+terminal shows some old contents and some new. This only lasts for a
+fraction of a second until the next chunk is received and processed.
+This is flickering. This also degrades performance, because redisplay
+is an expensive process and takes some time.
+
+ Fixing the flickering completely is not possible. Eat tries to
+decrease flickering by deferring redisplay. After receiving a chunk,
+Eat waits for a tiny fraction of a second. If another chunk arrives
+within the time, the redisplay is postponed. Then Eat waits for the
+same amount of time and this goes on. When timeout occurs, Eat
+processing the output and displays the output. This causes a small
+latency between output arrive and redisplay, but this is usually not
+long enough for human eyes to catch it. This waiting time can be
+configured with the following user option:
+
+ -- User Option: eat-minimum-latency
+ The value is the time in seconds to wait for the next chunk to
+ arrive. This is the minimum latency between the first chunk after
+ a redisplay and the next redisplay. For example, if you press
+ ‘<RET>’ in an empty Bash prompt, the next prompt won’t appear
+ before this much time.
+
+ You should set the time to something comfortable for you. You can
+ also set this to zero to disable waiting and showing the output
+ instantly, but this would likely cause a lot of flickering.
+
+ However, this waiting raises another problem. What if you execute
+the POSIX command ‘yes’ in the terminal? It will write infinite “y”s in
+the terminal without any delay between them anywhere. Eat will wait
+indefinitely for a delay between two chunks, which will never happen,
+unless the program is executed remotely and the connection is slow
+enough. So Eat has a limit for waiting, the display will be always be
+updated after this time. This limit also customizable:
+
+ -- User Option: eat-maximum-latency
+ The value is the time in seconds to wait at most for chunk. In
+ case of large burst of output, redisplay is never deferred more
+ than this many seconds, and cause a latency of up to this many
+ seconds.
+
+ You should set the time to something comfortable for you. You can
+ also set this to zero to disable waiting and showing the output
+ instantly, but this would likely cause a lot of flickering.
+
+ Due to some limitations, shell prompt annotations (*note Shell
+Integration::) can get messed up sometimes. Eat automatically corrects
+them after each terminal redisplay. However, this can have some
+performance impact when the terminal scrollback and display is large
+enough (unless the buffer is narrowed). So Eat defers the correction.
+
+ -- User Option: eat-shell-prompt-annotation-delay
+ The value is the time in seconds to wait for more output before
+ correcting shell prompt annotations.
+
+ You should set the time to something comfortable for you. You can
+ also set this to zero to disable waiting and correct annotations
+ instantly, but this may cause the terminal to slow down in some
+ cases.
+
+ The user options described in this chapter have reasonable default
+values, but the default values may change anytime.
+
+\1f
+File: docQL52HQ.info, Node: Common Problems, Next: Reporting Bugs, Prev: Performance Tuning, Up: Top
+
+21 Common Problems
+******************
+
+This chapter describe how to recognize and handle situations in which
+Eat does something unexpected, such as hangs, garbled text, etc.
+
+* Menu:
+
+* Not Recognized:: The program can’t recognize Eat.
+* Garbled Text:: When you get garbage on your terminal.
+* Input Invisible:: The input is not shown.
+* Not Responding:: What to do if Eat is unresponsive.
+* Signaled an Error:: The worst and the most unlikely bug.
+* Bugs in Manual:: What if there are problems in this manual?
+
+\1f
+File: docQL52HQ.info, Node: Not Recognized, Next: Garbled Text, Up: Common Problems
+
+21.1 Terminal Not Recognized
+============================
+
+If your program says that it can’t recognize the terminal, probably the
+‘TERM’ environment variable has a wrong value.
+
+ Check the value of ‘TERM’, if it’s not set to something like
+‘eat-...’, check the user option ‘eat-term-name’. If that’s correct
+that your shell might be changing the ‘TERM’ environment variable. If
+‘eat-term-name’ isn’t correct, customize to a suitable value and try
+again, your problem should be fixed.
+
+ If ‘TERM’ has the correct value, then probably the Terminfo databases
+of Eat are missing. This can happen if you have installed Eat without
+using the package from NonGNU ELPA (*note (emacs)Packages::). Check
+that whether the values of the environment variable ‘TERMINFO’ and the
+user option ‘eat-term-terminfo-directory’ match. If they match,
+customize ‘eat-term-terminfo-directory’ to the directory containing the
+Terminfo databases, the program should now recognize Eat. If they don’t
+match, then your shell is probably responsible for the problem.
+
+ If the program is not recognizing the terminal even when the correct
+directory is set as ‘eat-term-terminfo-directory’, probably the
+precompiled Terminfo databases aren’t working properly on your system.
+You can invoke the command ‘eat-compile-terminfo’ to recompile it for
+your system.
+
+ If you can’t find the directory containing Terminfo databases, you
+can compile it yourself. First, set ‘eat-term-terminfo-directory’ to
+the directory where to put the Terminfo databases. Then invoke the
+command ‘eat-compile-terminfo’ to compile the Terminfo databases.
+
+\1f
+File: docQL52HQ.info, Node: Garbled Text, Next: Input Invisible, Prev: Not Recognized, Up: Common Problems
+
+21.2 Garbled Text on Terminal
+=============================
+
+If the text on the terminal looks wrong, first check out the value of
+‘TERM’. Usually ‘TERM’ has a wrong value set, making programs send
+invalid escape sequences.
+
+ First, *note Not Recognized::; the problem is most likely because the
+program doesn’t recognize Eat, and it stays silent instead of reporting
+that.
+
+ If the problem isn’t resolved after following the instructions in the
+previous section, probably the precompiled Terminfo databases aren’t
+working properly on your system. Running the command
+‘eat-compile-terminfo’ will recompile it for your system.
+
+ If the problem still persists, may be your program is blindly
+assuming that the terminal is XTerm-compatible. If so, what you are
+seeing is the current state of “XTerm-compliance”. Though it’s not
+really a bug, we really want to know what’s problem so that we can fix
+it and improve XTerm-compliance. *Note Reporting Bugs:: for
+instructions on sending bug reports or feature request.
+
+ The other potential reason is that Eat is not working. This is
+definitely a bug, so please report it.
+
+\1f
+File: docQL52HQ.info, Node: Input Invisible, Next: Not Responding, Prev: Garbled Text, Up: Common Problems
+
+21.3 Input Invisible
+====================
+
+This can happen if the ‘stty’ program is unavailable on the system. Eat
+uses ‘stty’ to set various terminal settings including input echoing.
+Please install the ‘stty’ program to fix the problem.
+
+ If you are using Eat from Eshell (*note Eshell Terminal::), you might
+want to set ‘eat-eshell-fallback-if-stty-not-available’ to handle such
+cases. The user option can be set to three possible value, ‘t’ to
+automatically fallback to bare Eshell when ‘stty’ is not available,
+‘nil’ to do nothing, and ‘ask’ to ask interactively.
+
+\1f
+File: docQL52HQ.info, Node: Not Responding, Next: Signaled an Error, Prev: Input Invisible, Up: Common Problems
+
+21.4 Emacs or Eat Not Responding
+================================
+
+If you run something that outputs huge amount of data, your Emacs may
+not respond, and even quitting may not work. Quitting doesn’t work
+while doing something terminal related (output processing, for example),
+and that’s intentional, because quitting would mess up the terminal.
+
+ The best way to fix it is to stop the program, so that Eat is not
+overloaded. To avoid the problem in future, it is recommended to run
+those programs in faster terminals like bare Eshell (i.e. without
+Eat-Eshell), Comint, or external terminal emulators.
+
+\1f
+File: docQL52HQ.info, Node: Signaled an Error, Next: Bugs in Manual, Prev: Not Responding, Up: Common Problems
+
+21.5 Eat Signaled an Error
+==========================
+
+The worst thing that happen is that Eat might signal an error. It is
+the worst thing possible, because it messes up the terminal, and also a
+security hole. Fortunately, this is very rare. If you ever find any
+such bug, you should report the bug (*note Reporting Bugs::) as soon as
+possible with as much information as possible.
+
+ Once the error signaled, your best option is to delete the terminal
+and start a new one. But if you don’t want to delete the terminal, you
+can try invoking the command ‘reset’ from your shell. If for some
+reason you can’t do that, invoke the Emacs command ‘eat-reset’. This
+will reset most of the terminal state and give you a clean terminal to
+work with. However, it mayn’t work if you’re really unlucky, in that
+case deleting the terminal and starting a new one is your only option.
+
+\1f
+File: docQL52HQ.info, Node: Bugs in Manual, Prev: Signaled an Error, Up: Common Problems
+
+21.6 Bugs in Manual
+===================
+
+Human makes mistake, and we are no exceptions. But we are trying hard
+to improve Eat and it’s manual.
+
+ If you don’t understand something even after a careful rereading,
+that’s a bug.
+
+ If you find anything unclear in this manual, that’s a bug.
+
+ This manual’s job is make everything clear, so failing to do that
+indicates a bug.
+
+ If the built-in documentation and this manual don’t agree, one of
+them must be wrong, and that’s a bug.
+
+ If you Eat doesn’t behave as this manual describes, that’s a bug.
+
+ If you find any typing mistakes, that’s a bug.
+
+ If you find a bug, please report it. *Note Reporting Bugs:: for
+instruction on how to report it.
+
+\1f
+File: docQL52HQ.info, Node: Reporting Bugs, Next: Tracing the Terminal, Prev: Common Problems, Up: Top
+
+22 Reporting Bugs
+*****************
+
+We welcome bug reports and feature request. If you think you have found
+a bug, please report it. If you’re doubt, please send it anyway. We
+can’t promise that we’ll fix the bug or implement your feature idea, or
+always agree that it’s a bug, but we always want to hear from you.
+Please report bugs at <https://codeberg.org/akib/emacs-eat/issues/>.
+You may send the bug report by emailing to the maintainer (‘M-x
+describe-package <RET> eat <RET>’ would show the email address), but we
+prefer the former method, since the report is visible to everyone
+immediately.
+
+ The most important principle in reporting a bug is to report _facts_.
+Hypotheses and verbal descriptions are useful when they are more
+guesses, but in no way substitute for detailed raw data. You are
+encouraged to send you finding about bug, but please make sure to send
+the raw data needed to reproduce the bug.
+
+ For bug reports, please try to reproduce the bug with ‘emacs -Q’.
+This will disable loading your Emacs configuration, ruling out the
+potential bugs in your customizations. Please include enough
+information for us to reproduce the bug with ‘emacs -Q’, so that we have
+(or can get) enough information about the bug to fix it. Some bugs are
+hard to reproduce with ‘emacs -Q’, and some are not easily reproducible
+at all, in that case please give us the as much information as possible
+about Emacs configuration. Generally speaking, enough information
+includes (but not limited to):
+
+ • A description of the bug.
+
+ • The version of Eat you’re running. (‘M-x describe-package RET eat
+ RET’ would show the version.)
+
+ • The version of Emacs you’re running.
+
+ • Your Eat configuration, precisely.
+
+ • If you didn’t or can’t reproduce the bug with ‘emacs -Q’, as much
+ information as possible about Emacs configuration.
+
+ • Precisely what you did.
+
+ • Trace output, if you can generate it. (*Note Tracing the
+ Terminal:: for instruction to generate it.)
+
+ • Hardware and operating system names and versions.
+
+ • Anything else that you think would be helpful.
+
+ When in doubt whether to include something or not, please include it.
+It is better to include many useless information than to leave out
+something useful.
+
+ It is critical to send enough information to reproduce the bug. What
+is not critical to “narrow down” the example to the smallest possible –
+anything that reproduces the bug will suffice. (Of course, if you like
+doing experiments, the smaller the example, the better.)
+
+\1f
+File: docQL52HQ.info, Node: Tracing the Terminal, Next: GNU General Public License, Prev: Reporting Bugs, Up: Top
+
+23 Tracing the Terminal
+***********************
+
+When you run into a bug and want to report it, you’ll want to trace the
+terminal. Tracing means recording all the terminal activity, including
+creation, output, resizing and deleting.
+
+ To enable tracing, enable the global minor mode ‘eat-trace-mode’.
+This will trace all new terminals, including the terminal created inside
+Eshell.
+
+ Trace output for each command will be output in a buffer named
+‘*eat-trace BUFFER-NAME*: COMMAND’, where BUFFER-NAME is the buffer
+showing the terminal, and COMMAND is the command run in the terminal.
+
+ Only the terminals created after the trace mode is enabled are
+traced. So if you don’t have the mode enabled when you have found a
+bug, tracing can’t give you any information (as tracing is disabled,
+nothing has been recorded).
+
+ While submitting bug reports, please include the whole output in the
+trace output buffer. This contains many crucial information required to
+reproduce your bug.
+
+ You can replay the terminal by executing the command
+‘eat-trace-replay’ is the trace output buffer. You can use the key ‘n’
+or the key ‘<down>’ to show the next frame. This is not intended for
+ordinary users, it’s documented here only to help you debug Eat. You
+mustn’t rely on the behavior of this functionality to do anything else.
+
+\1f
+File: docQL52HQ.info, Node: GNU General Public License, Next: GNU Free Documentation License, Prev: Tracing the Terminal, Up: Top
+
+Appendix A GNU General Public License
+*************************************
+
+ Version 3, 29 June 2007
+
+ Copyright © 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>.
+
+\1f
+File: docQL52HQ.info, Node: GNU Free Documentation License, Next: Index, Prev: GNU General Public License, Up: Top
+
+Appendix B GNU Free Documentation License
+*****************************************
+
+ Version 1.3, 3 November 2008
+
+ Copyright © 2000, 2001, 2002, 2007, 2008 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.
+
+ 0. PREAMBLE
+
+ The purpose of this License is to make a manual, textbook, or other
+ functional and useful document “free” in the sense of freedom: to
+ assure everyone the effective freedom to copy and redistribute it,
+ with or without modifying it, either commercially or
+ noncommercially. Secondarily, this License preserves for the
+ author and publisher a way to get credit for their work, while not
+ being considered responsible for modifications made by others.
+
+ This License is a kind of “copyleft”, which means that derivative
+ works of the document must themselves be free in the same sense.
+ It complements the GNU General Public License, which is a copyleft
+ license designed for free software.
+
+ We have designed this License in order to use it for manuals for
+ free software, because free software needs free documentation: a
+ free program should come with manuals providing the same freedoms
+ that the software does. But this License is not limited to
+ software manuals; it can be used for any textual work, regardless
+ of subject matter or whether it is published as a printed book. We
+ recommend this License principally for works whose purpose is
+ instruction or reference.
+
+ 1. APPLICABILITY AND DEFINITIONS
+
+ This License applies to any manual or other work, in any medium,
+ that contains a notice placed by the copyright holder saying it can
+ be distributed under the terms of this License. Such a notice
+ grants a world-wide, royalty-free license, unlimited in duration,
+ to use that work under the conditions stated herein. The
+ “Document”, below, refers to any such manual or work. Any member
+ of the public is a licensee, and is addressed as “you”. You accept
+ the license if you copy, modify or distribute the work in a way
+ requiring permission under copyright law.
+
+ A “Modified Version” of the Document means any work containing the
+ Document or a portion of it, either copied verbatim, or with
+ modifications and/or translated into another language.
+
+ A “Secondary Section” is a named appendix or a front-matter section
+ of the Document that deals exclusively with the relationship of the
+ publishers or authors of the Document to the Document’s overall
+ subject (or to related matters) and contains nothing that could
+ fall directly within that overall subject. (Thus, if the Document
+ is in part a textbook of mathematics, a Secondary Section may not
+ explain any mathematics.) The relationship could be a matter of
+ historical connection with the subject or with related matters, or
+ of legal, commercial, philosophical, ethical or political position
+ regarding them.
+
+ The “Invariant Sections” are certain Secondary Sections whose
+ titles are designated, as being those of Invariant Sections, in the
+ notice that says that the Document is released under this License.
+ If a section does not fit the above definition of Secondary then it
+ is not allowed to be designated as Invariant. The Document may
+ contain zero Invariant Sections. If the Document does not identify
+ any Invariant Sections then there are none.
+
+ The “Cover Texts” are certain short passages of text that are
+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice
+ that says that the Document is released under this License. A
+ Front-Cover Text may be at most 5 words, and a Back-Cover Text may
+ be at most 25 words.
+
+ A “Transparent” copy of the Document means a machine-readable copy,
+ represented in a format whose specification is available to the
+ general public, that is suitable for revising the document
+ straightforwardly with generic text editors or (for images composed
+ of pixels) generic paint programs or (for drawings) some widely
+ available drawing editor, and that is suitable for input to text
+ formatters or for automatic translation to a variety of formats
+ suitable for input to text formatters. A copy made in an otherwise
+ Transparent file format whose markup, or absence of markup, has
+ been arranged to thwart or discourage subsequent modification by
+ readers is not Transparent. An image format is not Transparent if
+ used for any substantial amount of text. A copy that is not
+ “Transparent” is called “Opaque”.
+
+ Examples of suitable formats for Transparent copies include plain
+ ASCII without markup, Texinfo input format, LaTeX input format,
+ SGML or XML using a publicly available DTD, and standard-conforming
+ simple HTML, PostScript or PDF designed for human modification.
+ Examples of transparent image formats include PNG, XCF and JPG.
+ Opaque formats include proprietary formats that can be read and
+ edited only by proprietary word processors, SGML or XML for which
+ the DTD and/or processing tools are not generally available, and
+ the machine-generated HTML, PostScript or PDF produced by some word
+ processors for output purposes only.
+
+ The “Title Page” means, for a printed book, the title page itself,
+ plus such following pages as are needed to hold, legibly, the
+ material this License requires to appear in the title page. For
+ works in formats which do not have any title page as such, “Title
+ Page” means the text near the most prominent appearance of the
+ work’s title, preceding the beginning of the body of the text.
+
+ The “publisher” means any person or entity that distributes copies
+ of the Document to the public.
+
+ A section “Entitled XYZ” means a named subunit of the Document
+ whose title either is precisely XYZ or contains XYZ in parentheses
+ following text that translates XYZ in another language. (Here XYZ
+ stands for a specific section name mentioned below, such as
+ “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.)
+ To “Preserve the Title” of such a section when you modify the
+ Document means that it remains a section “Entitled XYZ” according
+ to this definition.
+
+ The Document may include Warranty Disclaimers next to the notice
+ which states that this License applies to the Document. These
+ Warranty Disclaimers are considered to be included by reference in
+ this License, but only as regards disclaiming warranties: any other
+ implication that these Warranty Disclaimers may have is void and
+ has no effect on the meaning of this License.
+
+ 2. VERBATIM COPYING
+
+ You may copy and distribute the Document in any medium, either
+ commercially or noncommercially, provided that this License, the
+ copyright notices, and the license notice saying this License
+ applies to the Document are reproduced in all copies, and that you
+ add no other conditions whatsoever to those of this License. You
+ may not use technical measures to obstruct or control the reading
+ or further copying of the copies you make or distribute. However,
+ you may accept compensation in exchange for copies. If you
+ distribute a large enough number of copies you must also follow the
+ conditions in section 3.
+
+ You may also lend copies, under the same conditions stated above,
+ and you may publicly display copies.
+
+ 3. COPYING IN QUANTITY
+
+ If you publish printed copies (or copies in media that commonly
+ have printed covers) of the Document, numbering more than 100, and
+ the Document’s license notice requires Cover Texts, you must
+ enclose the copies in covers that carry, clearly and legibly, all
+ these Cover Texts: Front-Cover Texts on the front cover, and
+ Back-Cover Texts on the back cover. Both covers must also clearly
+ and legibly identify you as the publisher of these copies. The
+ front cover must present the full title with all words of the title
+ equally prominent and visible. You may add other material on the
+ covers in addition. Copying with changes limited to the covers, as
+ long as they preserve the title of the Document and satisfy these
+ conditions, can be treated as verbatim copying in other respects.
+
+ If the required texts for either cover are too voluminous to fit
+ legibly, you should put the first ones listed (as many as fit
+ reasonably) on the actual cover, and continue the rest onto
+ adjacent pages.
+
+ If you publish or distribute Opaque copies of the Document
+ numbering more than 100, you must either include a machine-readable
+ Transparent copy along with each Opaque copy, or state in or with
+ each Opaque copy a computer-network location from which the general
+ network-using public has access to download using public-standard
+ network protocols a complete Transparent copy of the Document, free
+ of added material. If you use the latter option, you must take
+ reasonably prudent steps, when you begin distribution of Opaque
+ copies in quantity, to ensure that this Transparent copy will
+ remain thus accessible at the stated location until at least one
+ year after the last time you distribute an Opaque copy (directly or
+ through your agents or retailers) of that edition to the public.
+
+ It is requested, but not required, that you contact the authors of
+ the Document well before redistributing any large number of copies,
+ to give them a chance to provide you with an updated version of the
+ Document.
+
+ 4. MODIFICATIONS
+
+ You may copy and distribute a Modified Version of the Document
+ under the conditions of sections 2 and 3 above, provided that you
+ release the Modified Version under precisely this License, with the
+ Modified Version filling the role of the Document, thus licensing
+ distribution and modification of the Modified Version to whoever
+ possesses a copy of it. In addition, you must do these things in
+ the Modified Version:
+
+ A. Use in the Title Page (and on the covers, if any) a title
+ distinct from that of the Document, and from those of previous
+ versions (which should, if there were any, be listed in the
+ History section of the Document). You may use the same title
+ as a previous version if the original publisher of that
+ version gives permission.
+
+ B. List on the Title Page, as authors, one or more persons or
+ entities responsible for authorship of the modifications in
+ the Modified Version, together with at least five of the
+ principal authors of the Document (all of its principal
+ authors, if it has fewer than five), unless they release you
+ from this requirement.
+
+ C. State on the Title page the name of the publisher of the
+ Modified Version, as the publisher.
+
+ D. Preserve all the copyright notices of the Document.
+
+ E. Add an appropriate copyright notice for your modifications
+ adjacent to the other copyright notices.
+
+ F. Include, immediately after the copyright notices, a license
+ notice giving the public permission to use the Modified
+ Version under the terms of this License, in the form shown in
+ the Addendum below.
+
+ G. Preserve in that license notice the full lists of Invariant
+ Sections and required Cover Texts given in the Document’s
+ license notice.
+
+ H. Include an unaltered copy of this License.
+
+ I. Preserve the section Entitled “History”, Preserve its Title,
+ and add to it an item stating at least the title, year, new
+ authors, and publisher of the Modified Version as given on the
+ Title Page. If there is no section Entitled “History” in the
+ Document, create one stating the title, year, authors, and
+ publisher of the Document as given on its Title Page, then add
+ an item describing the Modified Version as stated in the
+ previous sentence.
+
+ J. Preserve the network location, if any, given in the Document
+ for public access to a Transparent copy of the Document, and
+ likewise the network locations given in the Document for
+ previous versions it was based on. These may be placed in the
+ “History” section. You may omit a network location for a work
+ that was published at least four years before the Document
+ itself, or if the original publisher of the version it refers
+ to gives permission.
+
+ K. For any section Entitled “Acknowledgements” or “Dedications”,
+ Preserve the Title of the section, and preserve in the section
+ all the substance and tone of each of the contributor
+ acknowledgements and/or dedications given therein.
+
+ L. Preserve all the Invariant Sections of the Document, unaltered
+ in their text and in their titles. Section numbers or the
+ equivalent are not considered part of the section titles.
+
+ M. Delete any section Entitled “Endorsements”. Such a section
+ may not be included in the Modified Version.
+
+ N. Do not retitle any existing section to be Entitled
+ “Endorsements” or to conflict in title with any Invariant
+ Section.
+
+ O. Preserve any Warranty Disclaimers.
+
+ If the Modified Version includes new front-matter sections or
+ appendices that qualify as Secondary Sections and contain no
+ material copied from the Document, you may at your option designate
+ some or all of these sections as invariant. To do this, add their
+ titles to the list of Invariant Sections in the Modified Version’s
+ license notice. These titles must be distinct from any other
+ section titles.
+
+ You may add a section Entitled “Endorsements”, provided it contains
+ nothing but endorsements of your Modified Version by various
+ parties—for example, statements of peer review or that the text has
+ been approved by an organization as the authoritative definition of
+ a standard.
+
+ You may add a passage of up to five words as a Front-Cover Text,
+ and a passage of up to 25 words as a Back-Cover Text, to the end of
+ the list of Cover Texts in the Modified Version. Only one passage
+ of Front-Cover Text and one of Back-Cover Text may be added by (or
+ through arrangements made by) any one entity. If the Document
+ already includes a cover text for the same cover, previously added
+ by you or by arrangement made by the same entity you are acting on
+ behalf of, you may not add another; but you may replace the old
+ one, on explicit permission from the previous publisher that added
+ the old one.
+
+ The author(s) and publisher(s) of the Document do not by this
+ License give permission to use their names for publicity for or to
+ assert or imply endorsement of any Modified Version.
+
+ 5. COMBINING DOCUMENTS
+
+ You may combine the Document with other documents released under
+ this License, under the terms defined in section 4 above for
+ modified versions, provided that you include in the combination all
+ of the Invariant Sections of all of the original documents,
+ unmodified, and list them all as Invariant Sections of your
+ combined work in its license notice, and that you preserve all
+ their Warranty Disclaimers.
+
+ The combined work need only contain one copy of this License, and
+ multiple identical Invariant Sections may be replaced with a single
+ copy. If there are multiple Invariant Sections with the same name
+ but different contents, make the title of each such section unique
+ by adding at the end of it, in parentheses, the name of the
+ original author or publisher of that section if known, or else a
+ unique number. Make the same adjustment to the section titles in
+ the list of Invariant Sections in the license notice of the
+ combined work.
+
+ In the combination, you must combine any sections Entitled
+ “History” in the various original documents, forming one section
+ Entitled “History”; likewise combine any sections Entitled
+ “Acknowledgements”, and any sections Entitled “Dedications”. You
+ must delete all sections Entitled “Endorsements.”
+
+ 6. COLLECTIONS OF DOCUMENTS
+
+ You may make a collection consisting of the Document and other
+ documents released under this License, and replace the individual
+ copies of this License in the various documents with a single copy
+ that is included in the collection, provided that you follow the
+ rules of this License for verbatim copying of each of the documents
+ in all other respects.
+
+ You may extract a single document from such a collection, and
+ distribute it individually under this License, provided you insert
+ a copy of this License into the extracted document, and follow this
+ License in all other respects regarding verbatim copying of that
+ document.
+
+ 7. AGGREGATION WITH INDEPENDENT WORKS
+
+ A compilation of the Document or its derivatives with other
+ separate and independent documents or works, in or on a volume of a
+ storage or distribution medium, is called an “aggregate” if the
+ copyright resulting from the compilation is not used to limit the
+ legal rights of the compilation’s users beyond what the individual
+ works permit. When the Document is included in an aggregate, this
+ License does not apply to the other works in the aggregate which
+ are not themselves derivative works of the Document.
+
+ If the Cover Text requirement of section 3 is applicable to these
+ copies of the Document, then if the Document is less than one half
+ of the entire aggregate, the Document’s Cover Texts may be placed
+ on covers that bracket the Document within the aggregate, or the
+ electronic equivalent of covers if the Document is in electronic
+ form. Otherwise they must appear on printed covers that bracket
+ the whole aggregate.
+
+ 8. TRANSLATION
+
+ Translation is considered a kind of modification, so you may
+ distribute translations of the Document under the terms of section
+ 4. Replacing Invariant Sections with translations requires special
+ permission from their copyright holders, but you may include
+ translations of some or all Invariant Sections in addition to the
+ original versions of these Invariant Sections. You may include a
+ translation of this License, and all the license notices in the
+ Document, and any Warranty Disclaimers, provided that you also
+ include the original English version of this License and the
+ original versions of those notices and disclaimers. In case of a
+ disagreement between the translation and the original version of
+ this License or a notice or disclaimer, the original version will
+ prevail.
+
+ If a section in the Document is Entitled “Acknowledgements”,
+ “Dedications”, or “History”, the requirement (section 4) to
+ Preserve its Title (section 1) will typically require changing the
+ actual title.
+
+ 9. TERMINATION
+
+ You may not copy, modify, sublicense, or distribute the Document
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense, or distribute it is void,
+ and will automatically terminate your rights under this License.
+
+ 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, receipt of a copy of some or all of the
+ same material does not give you any rights to use it.
+
+ 10. FUTURE REVISIONS OF THIS LICENSE
+
+ The Free Software Foundation may publish new, revised versions of
+ the GNU Free Documentation 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. See
+ <https://www.gnu.org/licenses/>.
+
+ Each version of the License is given a distinguishing version
+ number. If the Document specifies that a particular numbered
+ version of this License “or any later version” applies to it, you
+ have the option of following the terms and conditions either of
+ that specified version or of any later version that has been
+ published (not as a draft) by the Free Software Foundation. If the
+ Document does not specify a version number of this License, you may
+ choose any version ever published (not as a draft) by the Free
+ Software Foundation. If the Document specifies that a proxy can
+ decide which future versions of this License can be used, that
+ proxy’s public statement of acceptance of a version permanently
+ authorizes you to choose that version for the Document.
+
+ 11. RELICENSING
+
+ “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any
+ World Wide Web server that publishes copyrightable works and also
+ provides prominent facilities for anybody to edit those works. A
+ public wiki that anybody can edit is an example of such a server.
+ A “Massive Multiauthor Collaboration” (or “MMC”) contained in the
+ site means any set of copyrightable works thus published on the MMC
+ site.
+
+ “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0
+ license published by Creative Commons Corporation, a not-for-profit
+ corporation with a principal place of business in San Francisco,
+ California, as well as future copyleft versions of that license
+ published by that same organization.
+
+ “Incorporate” means to publish or republish a Document, in whole or
+ in part, as part of another Document.
+
+ An MMC is “eligible for relicensing” if it is licensed under this
+ License, and if all works that were first published under this
+ License somewhere other than this MMC, and subsequently
+ incorporated in whole or in part into the MMC, (1) had no cover
+ texts or invariant sections, and (2) were thus incorporated prior
+ to November 1, 2008.
+
+ The operator of an MMC Site may republish an MMC contained in the
+ site under CC-BY-SA on the same site at any time before August 1,
+ 2009, provided the MMC is eligible for relicensing.
+
+ADDENDUM: How to use this License for your documents
+====================================================
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and license
+notices just after the title page:
+
+ Copyright (C) YEAR YOUR NAME.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license is included in the section entitled ``GNU
+ Free Documentation License''.
+
+ If you have Invariant Sections, Front-Cover Texts and Back-Cover
+Texts, replace the “with...Texts.” line with this:
+
+ with the Invariant Sections being LIST THEIR TITLES, with
+ the Front-Cover Texts being LIST, and with the Back-Cover Texts
+ being LIST.
+
+ If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+ If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of free
+software license, such as the GNU General Public License, to permit
+their use in free software.
+
+\1f
+File: docQL52HQ.info, Node: Index, Prev: GNU Free Documentation License, Up: Top
+
+Appendix C Index
+****************
+
+\0\b[index\0\b]
+* Menu:
+
+* _eat_msg: Shell Integration. (line 95)
+* advertising colors: Colors. (line 36)
+* aliases, color: Colors. (line 20)
+* aliases, face: Colors. (line 20)
+* annotate, prompt: Shell Integration. (line 46)
+* annotate, shell prompt: Shell Integration. (line 47)
+* annotation, prompt: Shell Integration. (line 47)
+* annotation, shell prompt: Shell Integration. (line 47)
+* blinking cursor: Cursor Types. (line 3)
+* blinking text: Blinking Text. (line 3)
+* bold text: Fonts. (line 10)
+* bug reporting: Reporting Bugs. (line 3)
+* bugs in manual: Bugs in Manual. (line 3)
+* bugs, manual: Bugs in Manual. (line 3)
+* C-c C-c (“line mode”): Input Modes. (line 108)
+* C-c C-c (“semi-char mode”): Input Modes. (line 35)
+* C-c C-e (“line mode”): Input Modes. (line 117)
+* C-c C-e (“semi-char mode”): Input Modes. (line 80)
+* C-c C-j (“emacs mode”): Input Modes. (line 85)
+* C-c C-j (“line mode”): Input Modes. (line 117)
+* C-c C-k (“emacs mode”): Input Modes. (line 82)
+* C-c C-k (“semi-char mode”): Input Modes. (line 35)
+* C-c C-l (“emacs mode”): Input Modes. (line 99)
+* C-c C-l (“semi-char mode”): Input Modes. (line 99)
+* C-c C-n (“emacs mode”): Shell Integration. (line 38)
+* C-c C-n (“semi-char mode”): Shell Integration. (line 38)
+* C-c C-p (“emacs mode”): Shell Integration. (line 38)
+* C-c C-p (“semi-char mode”): Shell Integration. (line 38)
+* C-c C-r (“line mode”): Input Modes. (line 121)
+* C-c M-d (“emacs mode”): Input Modes. (line 85)
+* C-c M-d (“line mode”): Input Modes. (line 117)
+* C-c M-d (“semi-char mode”): Input Modes. (line 61)
+* C-c M-r (“line mode”): Input Modes. (line 121)
+* C-c M-s (“line mode”): Input Modes. (line 121)
+* C-c <SPC> (“line mode”): Input Modes. (line 102)
+* C-d (“line mode”): Input Modes. (line 108)
+* C-<down> (“line mode”): Input Modes. (line 121)
+* C-M-m (“char mode”): Input Modes. (line 70)
+* C-q (“semi-char mode”): Input Modes. (line 27)
+* C-<up> (“line mode”): Input Modes. (line 121)
+* C-x n d (“emacs mode”): Shell Integration. (line 43)
+* C-x n d (“semi-char mode”): Shell Integration. (line 43)
+* C-y (“semi-char mode”): Clipboard. (line 6)
+* cause of flickering: Performance Tuning. (line 19)
+* changing cursor: Cursor Types. (line 3)
+* char mode: Input Modes. (line 53)
+* clipboard: Clipboard. (line 3)
+* clipboard integration: Clipboard. (line 10)
+* color advertisement: Colors. (line 36)
+* color aliases: Colors. (line 20)
+* colors: Colors. (line 3)
+* common problems: Common Problems. (line 3)
+* confirm before kill: Querying Before Kill.
+ (line 3)
+* confirm before kill terminal: Querying Before Kill.
+ (line 3)
+* credential input: Password Input. (line 3)
+* cursor blinking: Cursor Types. (line 3)
+* cursor types: Cursor Types. (line 3)
+* customizing colors: Colors. (line 3)
+* customizing cursor: Cursor Types. (line 3)
+* customizing font families: Fonts. (line 24)
+* customizing semi-char mode: Input Modes. (line 38)
+* customizing semi-char mode keybindings: Input Modes. (line 38)
+* customizing semi-char mode keys: Input Modes. (line 38)
+* cwd tracking: Shell Integration. (line 22)
+* directory tracking: Shell Integration. (line 22)
+* display: Display. (line 3)
+* eat: Hello Terminal. (line 6)
+* eat not responding: Not Responding. (line 3)
+* eat signaled an error: Signaled an Error. (line 3)
+* eat, eshell: Eshell Terminal. (line 3)
+* eat-blink-mode: Blinking Text. (line 15)
+* eat-compile-terminfo: Not Recognized. (line 24)
+* eat-default-cursor-type: Cursor Types. (line 16)
+* eat-default-cursor-type <1>: Cursor Types. (line 16)
+* eat-enable-auto-line-mode: Shell Integration. (line 122)
+* eat-enable-auto-line-mode <1>: Shell Integration. (line 122)
+* eat-enable-blinking-text: Blinking Text. (line 10)
+* eat-enable-blinking-text <1>: Blinking Text. (line 10)
+* eat-enable-directory-tracking: Shell Integration. (line 31)
+* eat-enable-directory-tracking <1>: Shell Integration. (line 31)
+* eat-enable-kill-from-terminal: Clipboard. (line 17)
+* eat-enable-kill-from-terminal <1>: Clipboard. (line 17)
+* eat-enable-mouse: Mouse Tracking. (line 10)
+* eat-enable-mouse <1>: Mouse Tracking. (line 10)
+* eat-enable-shell-prompt-annotation: Shell Integration. (line 56)
+* eat-enable-shell-prompt-annotation <1>: Shell Integration. (line 56)
+* eat-enable-yank-to-terminal: Clipboard. (line 26)
+* eat-enable-yank-to-terminal <1>: Clipboard. (line 26)
+* eat-eshell-fallback-if-stty-not-available: Input Invisible. (line 10)
+* eat-eshell-mode: Eshell Terminal. (line 11)
+* eat-eshell-semi-char-non-bound-keys: Input Modes. (line 38)
+* eat-eshell-update-semi-char-mode-map: Input Modes. (line 47)
+* eat-fast-blink-frequency: Blinking Text. (line 38)
+* eat-fast-blink-frequency <1>: Blinking Text. (line 38)
+* eat-horizontal-bar-cursor-type: Cursor Types. (line 34)
+* eat-horizontal-bar-cursor-type <1>: Cursor Types. (line 34)
+* eat-input-chunk-size: Performance Tuning. (line 14)
+* eat-input-chunk-size <1>: Performance Tuning. (line 14)
+* eat-invisible-cursor-type: Cursor Types. (line 19)
+* eat-invisible-cursor-type <1>: Cursor Types. (line 19)
+* eat-line-auto-move-to-input: Input Modes. (line 112)
+* eat-line-input-history-isearch: Input Modes. (line 134)
+* eat-line-input-history-isearch <1>: Input Modes. (line 134)
+* eat-maximum-latency: Performance Tuning. (line 64)
+* eat-maximum-latency <1>: Performance Tuning. (line 64)
+* eat-message-handler-alist: Shell Integration. (line 102)
+* eat-message-handler-alist <1>: Shell Integration. (line 102)
+* eat-minimum-latency: Performance Tuning. (line 45)
+* eat-minimum-latency <1>: Performance Tuning. (line 45)
+* eat-narrow-to-shell-prompt: Shell Integration. (line 43)
+* eat-next-shell-prompt: Shell Integration. (line 38)
+* eat-previous-shell-prompt: Shell Integration. (line 38)
+* eat-project: Project-local Terminal.
+ (line 6)
+* eat-query-before-killing-running-terminal: Querying Before Kill.
+ (line 12)
+* eat-query-before-killing-running-terminal <1>: Querying Before Kill.
+ (line 12)
+* eat-reload: Input Modes. (line 47)
+* eat-reset: Signaled an Error. (line 12)
+* eat-semi-char-non-bound-keys: Input Modes. (line 38)
+* eat-send-command: Password Input. (line 10)
+* eat-shell-prompt-annotation-delay: Performance Tuning. (line 80)
+* eat-shell-prompt-annotation-delay <1>: Performance Tuning. (line 80)
+* eat-shell-prompt-annotation-failure: Shell Integration. (line 69)
+* eat-shell-prompt-annotation-failure-margin-indicator: Shell Integration.
+ (line 69)
+* eat-shell-prompt-annotation-position: Shell Integration. (line 64)
+* eat-shell-prompt-annotation-position <1>: Shell Integration.
+ (line 64)
+* eat-shell-prompt-annotation-running: Shell Integration. (line 69)
+* eat-shell-prompt-annotation-running-margin-indicator: Shell Integration.
+ (line 69)
+* eat-shell-prompt-annotation-success: Shell Integration. (line 69)
+* eat-shell-prompt-annotation-success-margin-indicator: Shell Integration.
+ (line 69)
+* eat-sixel-aspect-ratio: Sixel. (line 17)
+* eat-sixel-aspect-ratio <1>: Sixel. (line 17)
+* eat-sixel-render-formats: Sixel. (line 27)
+* eat-sixel-render-formats <1>: Sixel. (line 27)
+* eat-sixel-scale: Sixel. (line 13)
+* eat-sixel-scale <1>: Sixel. (line 13)
+* eat-slow-blink-frequency: Blinking Text. (line 32)
+* eat-slow-blink-frequency <1>: Blinking Text. (line 32)
+* eat-term-bold: Fonts. (line 10)
+* eat-term-bold <1>: Fonts. (line 13)
+* eat-term-fast-blink: Blinking Text. (line 23)
+* eat-term-italic: Fonts. (line 16)
+* eat-term-name: Colors. (line 48)
+* eat-term-name <1>: Colors. (line 48)
+* eat-term-name <2>: Not Recognized. (line 9)
+* eat-term-scrollback-size: Scrollback. (line 17)
+* eat-term-scrollback-size <1>: Scrollback. (line 17)
+* eat-term-slow-blink: Blinking Text. (line 23)
+* eat-term-terminfo-directory: Not Recognized. (line 15)
+* eat-trace-mode: Tracing the Terminal.
+ (line 10)
+* eat-trace-replay: Tracing the Terminal.
+ (line 27)
+* eat-update-semi-char-mode-map: Input Modes. (line 47)
+* eat-vertical-bar-cursor-type: Cursor Types. (line 27)
+* eat-vertical-bar-cursor-type <1>: Cursor Types. (line 27)
+* eat-very-visible-cursor-type: Cursor Types. (line 22)
+* eat-very-visible-cursor-type <1>: Cursor Types. (line 22)
+* eat-very-visible-horizontal-bar-cursor-type: Cursor Types. (line 37)
+* eat-very-visible-horizontal-bar-cursor-type <1>: Cursor Types.
+ (line 37)
+* eat-very-visible-vertical-bar-cursor-type: Cursor Types. (line 30)
+* eat-very-visible-vertical-bar-cursor-type <1>: Cursor Types.
+ (line 30)
+* eat-yank: Clipboard. (line 6)
+* eat-yank-pop: Clipboard. (line 6)
+* emacs mode: Input Modes. (line 73)
+* emacs not responding: Not Responding. (line 3)
+* environment variable, TERM: Colors. (line 43)
+* eshell: Eshell Terminal. (line 3)
+* eshell terminal: Eshell Terminal. (line 3)
+* eshell terminal emulation: Eshell Terminal. (line 3)
+* eshell, eat: Eshell Terminal. (line 3)
+* face aliases: Colors. (line 20)
+* faint text: Fonts. (line 13)
+* fixing flickering: Performance Tuning. (line 35)
+* flickering: Performance Tuning. (line 19)
+* flickering fix: Performance Tuning. (line 35)
+* font family: Fonts. (line 19)
+* fonts: Fonts. (line 3)
+* garbled text: Garbled Text. (line 3)
+* hello terminal: Hello Terminal. (line 3)
+* input invisible: Input Invisible. (line 3)
+* input mode, char: Input Modes. (line 52)
+* input mode, emacs: Input Modes. (line 72)
+* input mode, line: Input Modes. (line 89)
+* input mode, semi-char: Input Modes. (line 18)
+* input mode, semi-char, adding exceptions: Input Modes. (line 38)
+* input mode, semi-char, customizing: Input Modes. (line 38)
+* input mode, semi-char, exception, add: Input Modes. (line 38)
+* input modes: Input Modes. (line 3)
+* input, credential: Password Input. (line 3)
+* input, invisible: Input Invisible. (line 3)
+* input, password: Password Input. (line 3)
+* inputting exceptional characters: Input Modes. (line 27)
+* integration, shell: Shell Integration. (line 3)
+* integration, shell, line mode: Shell Integration. (line 113)
+* introduction: Intro. (line 3)
+* invisible input: Input Invisible. (line 3)
+* invisible, input: Input Invisible. (line 3)
+* italic text: Fonts. (line 16)
+* keybinding mode, char: Input Modes. (line 53)
+* keybinding mode, emacs: Input Modes. (line 73)
+* keybinding mode, line: Input Modes. (line 90)
+* keybinding mode, semi-char: Input Modes. (line 19)
+* keybinding mode, semi-char, adding exceptions: Input Modes. (line 38)
+* keybinding mode, semi-char, customizing: Input Modes. (line 38)
+* keybinding mode, semi-char, exception, add: Input Modes. (line 38)
+* keybinding modes: Input Modes. (line 3)
+* keybindings, char mode: Input Modes. (line 53)
+* keybindings, emacs mode: Input Modes. (line 73)
+* keybindings, line mode: Input Modes. (line 90)
+* keybindings, semi-char mode: Input Modes. (line 19)
+* keybindings, semi-char mode, adding exceptions: Input Modes.
+ (line 38)
+* keybindings, semi-char mode, customizing: Input Modes. (line 38)
+* keybindings, semi-char mode, exception, add: Input Modes. (line 38)
+* keyboard: Keyboard. (line 3)
+* latency: Performance Tuning. (line 35)
+* line mode: Input Modes. (line 90)
+* line mode integration: Shell Integration. (line 114)
+* line mode shell integration: Shell Integration. (line 114)
+* M-n (“line mode”): Input Modes. (line 121)
+* M-p (“line mode”): Input Modes. (line 121)
+* M-r (“line mode”): Input Modes. (line 121)
+* M-RET (“char mode”): Input Modes. (line 70)
+* M-y (“semi-char mode”): Clipboard. (line 6)
+* manual, bugs: Bugs in Manual. (line 3)
+* manual, typos: Bugs in Manual. (line 3)
+* mode, char: Input Modes. (line 53)
+* mode, emacs: Input Modes. (line 73)
+* mode, line: Input Modes. (line 90)
+* mode, semi-char: Input Modes. (line 19)
+* mode, semi-char, adding exceptions: Input Modes. (line 38)
+* mode, semi-char, customizing: Input Modes. (line 38)
+* mode, semi-char, exception, add: Input Modes. (line 38)
+* modes, input: Input Modes. (line 3)
+* modes, keybinding: Input Modes. (line 3)
+* mouse: Mouse. (line 3)
+* mouse tracking: Mouse Tracking. (line 3)
+* narrow to prompt: Shell Integration. (line 43)
+* narrow to shell prompt: Shell Integration. (line 43)
+* narrow, prompt: Shell Integration. (line 43)
+* narrow, shell prompt: Shell Integration. (line 43)
+* navigation, prompt: Shell Integration. (line 34)
+* not recognized: Not Recognized. (line 3)
+* not responding, eat: Not Responding. (line 3)
+* not responding, emacs: Not Responding. (line 3)
+* password input: Password Input. (line 3)
+* performance tuning: Performance Tuning. (line 3)
+* problem, common: Common Problems. (line 3)
+* problem, eat not responding: Not Responding. (line 3)
+* problem, eat signaled an error: Signaled an Error. (line 3)
+* problem, emacs not responding: Not Responding. (line 3)
+* problem, garbled text: Garbled Text. (line 3)
+* problem, not recognized: Not Recognized. (line 3)
+* problem, not responding, eat: Not Responding. (line 3)
+* problem, not responding, emacs: Not Responding. (line 3)
+* problem, reporting: Reporting Bugs. (line 3)
+* problem, signaled an error: Signaled an Error. (line 3)
+* problem, terminal not recognized: Not Recognized. (line 3)
+* problem, text garbled: Garbled Text. (line 3)
+* problems, bugs in manual: Bugs in Manual. (line 3)
+* problems, bugs, manual: Bugs in Manual. (line 3)
+* problems, manual, bugs: Bugs in Manual. (line 3)
+* problems, manual, typos: Bugs in Manual. (line 3)
+* problems, typos in manual: Bugs in Manual. (line 3)
+* problems, typos, manual: Bugs in Manual. (line 3)
+* project terminal: Project-local Terminal.
+ (line 3)
+* project’s terminal: Project-local Terminal.
+ (line 3)
+* project-local terminal: Project-local Terminal.
+ (line 3)
+* prompt annotation: Shell Integration. (line 47)
+* prompt navigation: Shell Integration. (line 35)
+* querying before kill: Querying Before Kill.
+ (line 3)
+* querying before kill terminal: Querying Before Kill.
+ (line 3)
+* reason behind flickering: Performance Tuning. (line 19)
+* reporting bugs: Reporting Bugs. (line 3)
+* <RET> (“line mode”): Input Modes. (line 102)
+* scrollback: Scrollback. (line 3)
+* semi-char mode: Input Modes. (line 19)
+* shell integration: Shell Integration. (line 3)
+* shell navigation, shell prompt: Shell Integration. (line 35)
+* shell prompt annotation: Shell Integration. (line 47)
+* shell prompt navigation: Shell Integration. (line 35)
+* signaled an error: Signaled an Error. (line 3)
+* sixel: Sixel. (line 3)
+* slant text: Fonts. (line 16)
+* <TAB> (“line mode”): Input Modes. (line 121)
+* TERM: Colors. (line 43)
+* TERM environment variable: Colors. (line 43)
+* terminal emulation, eshell: Eshell Terminal. (line 3)
+* terminal not recognized: Not Recognized. (line 3)
+* terminal recording: Tracing the Terminal.
+ (line 3)
+* terminal tracing: Tracing the Terminal.
+ (line 3)
+* terminal, eshell: Eshell Terminal. (line 3)
+* terminal, hello: Hello Terminal. (line 3)
+* terminal, kill, confirm: Querying Before Kill.
+ (line 3)
+* terminal, kill, query: Querying Before Kill.
+ (line 3)
+* terminal, project: Project-local Terminal.
+ (line 3)
+* terminal, project-local: Project-local Terminal.
+ (line 3)
+* text, blinking: Blinking Text. (line 3)
+* text, bold: Fonts. (line 10)
+* text, faint: Fonts. (line 13)
+* text, font family: Fonts. (line 19)
+* text, italic: Fonts. (line 16)
+* text, slant: Fonts. (line 16)
+* tracing the terminal: Tracing the Terminal.
+ (line 3)
+* tracking cwd: Shell Integration. (line 21)
+* tracking directory: Shell Integration. (line 22)
+* tracking mouse: Mouse Tracking. (line 3)
+* tracking working directory: Shell Integration. (line 22)
+* tuning performance: Performance Tuning. (line 3)
+* types, cursor: Cursor Types. (line 3)
+* typos in manual: Bugs in Manual. (line 3)
+* typos, manual: Bugs in Manual. (line 3)
+* window-adjust-process-window-size-function: Display. (line 11)
+* working directory tracking: Shell Integration. (line 22)
+* yanking: Clipboard. (line 6)
+
+
+\1f
+Tag Table:
+Node: Top\7f721
+Node: Intro\7f2983
+Node: Hello Terminal\7f3829
+Node: Project-local Terminal\7f4961
+Node: Eshell Terminal\7f5469
+Node: Keyboard\7f6664
+Node: Mouse\7f7662
+Node: Input Modes\7f8046
+Ref: Semi-char Mode\7f8745
+Ref: Char Mode\7f10496
+Ref: Emacs Mode\7f11342
+Ref: Line Mode\7f12018
+Node: Password Input\7f14724
+Node: Shell Integration\7f15433
+Ref: Directory tracking\7f16175
+Ref: Shell Prompt Navigation\7f16735
+Ref: Shell Prompt Annotation\7f17280
+Ref: Message Passing\7f19113
+Ref: Line Mode Integration\7f20412
+Node: Querying Before Kill\7f20852
+Node: Display\7f21853
+Node: Scrollback\7f22479
+Node: Cursor Types\7f23418
+Node: Mouse Tracking\7f25880
+Node: Clipboard\7f26429
+Node: Colors\7f27774
+Node: Fonts\7f30502
+Node: Sixel\7f31663
+Node: Blinking Text\7f33105
+Node: Performance Tuning\7f35117
+Node: Common Problems\7f39780
+Node: Not Recognized\7f40430
+Node: Garbled Text\7f42205
+Node: Input Invisible\7f43476
+Node: Not Responding\7f44196
+Node: Signaled an Error\7f44927
+Node: Bugs in Manual\7f45941
+Node: Reporting Bugs\7f46766
+Node: Tracing the Terminal\7f49486
+Node: GNU General Public License\7f50968
+Node: GNU Free Documentation License\7f88787
+Node: Index\7f114156
+\1f
+End Tag Table
+
+\1f
+Local Variables:
+coding: utf-8
+End:
--- /dev/null
+\input texinfo
+
+@comment %**start of header
+@setfilename eat.info
+@set UPDATED 15 December 2023
+@set VERSION 0.9.4
+@documentencoding UTF-8
+@codequotebacktick on
+@codequoteundirected on
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex ky cp
+@settitle Eat User Manual, version @value{VERSION}
+@comment %**end of header
+
+@copying
+This manual is for Eat (version @value{VERSION}, @value{UPDATED}), a
+terminal emulator for Emacs.
+
+Copyright @copyright{} 2022, 2023 Akib Azmain Turja.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
+copy of the license is included in the section entitled ``GNU Free
+Documentation License''.
+@end quotation
+@end copying
+
+@dircategory Emacs
+@direntry
+* Eat: (eat). Emulate A Terminal.
+@end direntry
+
+@titlepage
+@title Eat User Manual
+@subtitle For version @value{VERSION}
+@author Akib Azmain Turja
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+@ifnottex
+@node Top
+@top Eat Manual
+@insertcopying
+@end ifnottex
+
+@menu
+Introduction
+* Intro:: What is Eat?
+* Hello Terminal:: Starting Eat's terminal for the first time.
+* Project-local Terminal:: One project, one terminal.
+* Eshell Terminal:: Eat's terminal emulation in Eshell.
+
+Basic Operations
+* Keyboard:: Most keyboard keys are captured by Eat.
+* Mouse:: Eat supports mouse.
+* Input Modes:: Input modes for various use-cases.
+* Password Input:: Safely inputting credentials.
+
+Advanced Customizations
+* Shell Integration:: Getting the most from Eat and your shell.
+* Querying Before Kill:: Confirming before you kill your terminal.
+* Display:: The region where everything is shown.
+* Scrollback:: Region for things that went out of display.
+* Cursor Types:: Cursor can displayed in many forms.
+* Mouse Tracking:: Eat tracks mouse, but this can be changed.
+* Clipboard:: Integrating kill ring with terminal.
+* Colors:: Eat can show more than sixteen million colors.
+* Fonts:: Eat can show up to sixteen different fonts.
+* Blinking Text:: Annoying blinking texts.
+* Performance Tuning:: Fine tuning to maximize performance.
+
+Recovering from Problems
+* Common Problems:: Common problem, and fixes.
+* Reporting Bugs:: How to report problems?
+* Tracing the Terminal:: Gathering some crucial information to
+ reproduce a bug.
+
+Appendices
+* GNU General Public License:: Copying condition for Eat.
+* GNU Free Documentation License:: Copying conditions of this manual.
+* Index:: A list of various things.
+@end menu
+
+@part Part I:@* Introduction
+
+@node Intro
+@cindex introduction
+@chapter Introduction
+
+@abbr{Eat, Emulate A Terminal} is a terminal emulator for Emacs. It
+emulates a XTerm-like terminal, just like many other terminal
+emulators. But it has some key features that make Eat distinct from
+other terminal emulators.
+
+Firstly, it's in Emacs, which means you don't need to leave the
+comfort of Emacs to use terminal.
+
+Secondly, it's easy and convenient to use. It is tries to stay out of
+your way, allowing you to maximize your productivity.
+
+Finally, special care has been taken while designing the keybindings,
+so that the terminal doesn't conflict with Emacs default keybindings
+on both graphical display and text display, while still allowing you
+to run full screen programs like Emacs within the terminal.
+
+@node Hello Terminal
+@cindex hello terminal
+@cindex terminal, hello
+@chapter Hello Terminal
+
+@findex eat
+The terminal can be started with @kbd{M-x eat}. It'll create a
+terminal and run the default shell
+(@pxref{Interactive Shell,,, emacs, GNU Emacs Manual}) in it. You
+should get a shell prompt and be able to write shell commands and
+execute them. Full screen programs like @samp{htop}, @samp{lynx} and
+Emacs will work inside it, just like any other terminal. (If the
+terminal doesn't work as expected, @pxref{Common Problems}.)
+
+If an Eat terminal already exists, @kbd{M-x eat} will switch to it.
+To create a new terminal, call it with a prefix argument like this,
+@kbd{C-u M-x eat}.
+
+If you give it a numeric prefix argument N, for example
+@kbd{C-u 42 M-x eat}, it'll switch to a terminal in the buffer
+@file{*eat*<N>}, @file{*eat*<42>} for example, or it'll create a new
+terminal if that buffer doesn't exist.
+
+If you give it double prefix argument, for example
+@kbd{C-u C-u M-x eat}, you'll be prompted for the program or shell
+command to run, and it'll be run in a newly created terminal.
+
+@node Project-local Terminal
+@cindex project-local terminal
+@cindex terminal, project-local
+@cindex project's terminal
+@cindex project terminal
+@cindex terminal, project
+@chapter Project-local Terminal
+
+@findex eat-project
+Usually, you don't use a single terminal for everything, instead you
+open a terminal for each project that needs it. So there is command
+named @command{eat-project}. It opens a new terminal in project root
+directory, or switches to a already existing project terminal. It too
+accepts prefix argument, just like the ordinary @command{eat} command.
+
+@node Eshell Terminal
+@cindex eshell terminal
+@cindex terminal, eshell
+@cindex eshell terminal emulation
+@cindex terminal emulation, eshell
+@cindex eat, eshell
+@cindex eshell, eat
+@cindex eshell
+@chapter Eshell Terminal Emulation
+
+Eat also supports terminal emulation outside Eat's terminal. So you
+can emulate terminal in Eshell (@pxref{Top,,, eshell, Eshell manual})
+with Eat. After configuring Eshell to use Eat for terminal emulation,
+you can run any full screen terminal program in Eshell.
+
+@findex eat-eshell-mode
+To enable terminal emulation in Eshell, enable the global minor mode
+@command{eat-eshell-mode}. It will enable Eat's terminal emulation in
+Eshell. To disable the terminal emulation, disable the minor mode.
+
+You can't toggle the global minor mode while any Eshell command is
+running, so terminate any Eshell command or wait them to finish before
+toggling the mode.
+
+Unless stated otherwise, everything described in this manual about
+Eat terminal also applies to Eshell terminal emulation.
+
+You might also want to set @code{eshell-visual-commands} user option
+to nil, since they'll work in Eshell when @code{eat-eshell-mode} is
+enabled.
+
+If you want to run Eshell visual commands with Eat, you can enable the
+global minor mode @command{eat-eshell-visual-command-mode}.
+
+@part Part II:@* Basic Operations
+
+@node Keyboard
+@cindex keyboard
+@chapter Keyboard
+
+Just like any other text terminal, the primary interaction device with
+Eat terminal is the keyboard. Eat forwards all supported keyboard
+events like @kbd{a}, @kbd{E}, @kbd{RET}, @kbd{C-a} to the terminal.
+
+However, this conflict with Emacs keybinding conventions, and makes it
+almost impossible to call any other Emacs command. So, by default,
+Eat doesn't intercept the key sequences beginning with the following
+keys and lets Emacs to handle them: @kbd{C-\}, @kbd{C-c}, @kbd{C-x},
+@kbd{C-g}, @kbd{C-h}, @kbd{C-M-c}, @kbd{C-u}, @kbd{C-q}, @kbd{M-x},
+@kbd{M-:}, @kbd{M-!} and @kbd{M-&}.
+
+To input the above key sequences, prefix them with @kbd{C-q}.
+@kbd{C-q} reads the next event and sends to directly to the terminal.
+For example, to input @kbd{M-:}, use the key sequence @kbd{C-q M-:}.
+
+For an alternative way to input these exceptional characters,
+@pxref{Char Mode}.
+
+@node Mouse
+@cindex mouse
+@chapter Mouse
+
+Eat supports mouse tracking. That means in programs like Emacs,
+@samp{htop}, etc, that support mouse, you can hover and click on
+text and buttons. You can also use your mouse wheel to scroll text,
+if the program supports it.
+
+@xref{Mouse Tracking} to configure mouse tracking.
+
+@node Input Modes
+@cindex input modes
+@cindex modes, input
+@cindex keybinding modes
+@cindex modes, keybinding
+@chapter Input Modes
+
+By default, Eat forwards all supported keys to terminals, except some
+exceptions. It is possible to input them with @kbd{C-q}, but it is
+not very convenient.
+
+To conveniently input those character, they should be bound to input
+themselves to the terminal (i.e. pressing @kbd{M-x} will input
+@kbd{M-x}, bypassing Emacs). But this is conflicts with Emacs's
+default keybindings, so this can't done, at least by default.
+
+To overcome the problem, Eat implements several ``input modes''. Each
+input mode has a different set of keybindings for different
+applications.
+
+@anchor{Semi-char Mode}
+@cindex semi-char mode
+@cindex mode, semi-char
+@cindex keybindings, semi-char mode
+@cindex keybinding mode, semi-char
+@cindex input mode, semi-char
+@section Semi-char Mode
+
+``Semi-char mode'' is the default input mode of Eat. This works for
+most inputs. It forwards all keys, except @kbd{C-\}, @kbd{C-c},
+@kbd{C-x}, @kbd{C-g}, @kbd{C-h}, @kbd{C-M-c}, @kbd{C-u}, @kbd{M-x},
+@kbd{C-q}, @kbd{M-:}, @kbd{M-!}, @kbd{M-&} and some other keys, Emacs
+handles them.
+
+@cindex inputting exceptional characters
+@kindex C-q @r{(``semi-char mode'')}
+To input these exceptions, there is a key @kbd{C-q}. This reads the
+next input event and sends that as the input. For example, the key
+sequences @kbd{C-q M-:} inputs @kbd{M-:}, @kbd{C-q C-g} inputs
+@kbd{C-g}.
+
+Input methods (@pxref{Input Methods,,, emacs, GNU Emacs Manual}) work
+in this mode, so, unlike Term (@pxref{Terminal emulator, Emacs
+Terminal Emulator, Emacs Terminal Emulator, emacs, GNU Emacs Manual}),
+Emacs built-in terminal emulator, you can still input any character.
+
+@kindex C-c C-c @r{(``semi-char mode'')}
+@kindex C-c C-k @r{(``semi-char mode'')}
+In ``semi-char mode'', @kbd{C-c C-c} sends a @kbd{C-c}, just for
+convenience, and @kbd{C-c C-k} kills the terminal program.
+
+@cindex customizing semi-char mode
+@cindex customizing semi-char mode keys
+@cindex customizing semi-char mode keybindings
+@cindex mode, semi-char, customizing
+@cindex keybindings, semi-char mode, customizing
+@cindex keybinding mode, semi-char, customizing
+@cindex input mode, semi-char, customizing
+@cindex mode, semi-char, adding exceptions
+@cindex keybindings, semi-char mode, adding exceptions
+@cindex keybinding mode, semi-char, adding exceptions
+@cindex input mode, semi-char, adding exceptions
+@cindex mode, semi-char, exception, add
+@cindex keybindings, semi-char mode, exception, add
+@cindex keybinding mode, semi-char, exception, add
+@cindex input mode, semi-char, exception, add
+@vindex eat-semi-char-non-bound-keys
+@vindex eat-eshell-semi-char-non-bound-keys
+You can customize the exceptions by customizing the user option
+@code{eat-semi-char-non-bound-keys}, and
+@code{eat-eshell-semi-char-non-bound-keys} for Eshell integration.
+Both user options contain a list of keys of form @code{[@var{key}]},
+where @var{key} is a key not to bind. @var{key} mustn't contain meta
+modifier. To not bind a key with meta modifier, use a vector of form
+@code{[?\e @var{key}]}, where @var{key} is the key without meta
+modifier. These user options contain all the ``semi-char'' mode
+exceptions listed above, plus some more exceptions.
+
+@findex eat-update-semi-char-mode-map
+@findex eat-eshell-update-semi-char-mode-map
+@findex eat-reload
+If you set the user options manually (for example, with @code{setq}),
+you must call @code{eat-update-semi-char-mode-map} or
+@code{eat-eshell-update-semi-char-mode-map} respectively, and finally
+reload Eat (you can do this with the command @command{eat-reload}).
+Or alternatively you can set the user options before Eat is loaded.
+
+@anchor{Char Mode}
+@cindex char mode
+@cindex mode, char
+@cindex keybindings, char mode
+@cindex keybinding mode, char
+@cindex input mode, char
+@section Char Mode
+
+By default, Eat is in ``semi-char mode''. In this input mode, Eat
+forwards all supported keys to terminals, except some exceptions,
+@pxref{Semi-char Mode}. It is possible to input them with @kbd{C-q},
+but it is not very convenient.
+
+@kindex C-c M-d @r{(``semi-char mode'')}
+To overcome this problem, Eat implements another input mode called
+``char mode''. To switch to ``char mode'', press @kbd{C-c M-d} in
+``semi-char mode''. In Eshell, the command
+@command{eshell-toggle-direct-send} is remapped to enable
+``char-mode'', which is usually bound to @kbd{C-c M-d}.
+
+In this input mode, Eat forwards all supported keys. However, input
+methods still work in this mode, so you can still input keys that are
+not on your keyboard.
+
+@kindex C-M-m @r{(``char mode'')}
+@kindex M-RET @r{(``char mode'')}
+To get out of ``char mode'', press @kbd{C-M-m} or @kbd{M-@key{RET}},
+this switches back to ``semi-char mode''.
+
+@anchor{Emacs Mode}
+@cindex emacs mode
+@cindex mode, emacs
+@cindex keybindings, emacs mode
+@cindex keybinding mode, emacs
+@cindex input mode, emacs
+@section Emacs Mode
+
+In ``emacs mode'', no input events are send to the terminal. In this
+mode, you can interact with the terminal buffer just like a regular
+buffer. However, you are not allowed to change the buffer contents.
+
+@kindex C-c C-e @r{(``semi-char mode'')}
+To switch to ``emacs mode'', press @kbd{C-c C-e} from ``semi-char
+mode''.
+
+@kindex C-c C-k @r{(``emacs mode'')}
+In this mode, @kbd{C-c C-k} kills the terminal program like in
+``semi-char mode''.
+
+@kindex C-c C-j @r{(``emacs mode'')}
+@kindex C-c M-d @r{(``emacs mode'')}
+From ``emacs mode'', you can switch to ``semi-char mode'' with
+@kbd{C-c C-j} and to ``char mode'' with @kbd{C-c M-d}. In Eshell, the
+command @command{eshell-toggle-direct-send} is remapped to enable
+``char-mode'', which is usually bound to @kbd{C-c M-d}.
+
+@anchor{Line Mode}
+@cindex line mode
+@cindex mode, line
+@cindex keybindings, line mode
+@cindex keybinding mode, line
+@cindex input mode, line
+@section Line Mode
+
+In ``line mode'', input is sent one line at a line, similar to Comint
+or Shell mode (@pxref{Interactive Shell,,, emacs, GNU Emacs Manual}).
+Like ``emacs mode'', you can interact with buffer as you wish; but at
+the very end of the buffer, you can edit the input line with usual
+Emacs commands. This is not available in Eshell.
+
+@kindex C-c C-l @r{(``semi-char mode'')}
+@kindex C-c C-l @r{(``emacs mode'')}
+To enter ``line mode'', press @kbd{C-c C-l} from ``semi-char mode'' or
+``emacs mode''.
+
+@kindex @key{RET} @r{(``line mode'')}
+@kindex C-c @key{SPC} @r{(``line mode'')}
+@kbd{@key{RET}} sends the current input with a trailing newline, and
+clear the input area for new input to be written. When called with a
+prefix argument, no newline is appended before sending input. To
+input a newline character without actually sending it, you can press
+@kbd{C-c @key{SPC}}.
+
+@kindex C-c C-c @r{(``line mode'')}
+@kindex C-d @r{(``line mode'')}
+@kbd{C-c C-c} discards the input completely and sends an interrupt to
+the terminal. @kbd{C-d} deletes the character after the point, or
+sends EOF if the input is empty.
+
+@vindex eat-line-auto-move-to-input
+You can't modify the terminal in ``line mode'', you can write only in
+the input line. Eat automatically moves the point to the input line
+if you try to insert character in the terminal region. This behavior
+can be disabled by customizing @code{eat-line-auto-move-to-input} to
+@code{nil}.
+
+@kindex C-c C-e @r{(``line mode'')}
+@kindex C-c C-j @r{(``line mode'')}
+@kindex C-c M-d @r{(``line mode'')}
+You can exit to ``emacs mode'', ``semi-char mode'' or ``char mode''
+with @kbd{C-c C-e}, @kbd{C-c C-j} or @kbd{C-c M-d} respectively. If
+there's any pending input when exiting line mode, it is sent as is to
+the terminal.
+
+@kindex M-p @r{(``line mode'')}
+@kindex M-n @r{(``line mode'')}
+@kindex C-@key{up} @r{(``line mode'')}
+@kindex C-@key{down} @r{(``line mode'')}
+@kindex M-r @r{(``line mode'')}
+@kindex C-c M-r @r{(``line mode'')}
+@kindex C-c M-s @r{(``line mode'')}
+@kindex C-c C-r @r{(``line mode'')}
+@kindex @key{TAB} @r{(``line mode'')}
+The input history is recorded. You can cycle through the history with
+@kbd{M-p} and @kbd{M-n}, and also with @kbd{C-@key{up}} and
+@kbd{C-@key{down}}. @kbd{C-c M-r} and @kbd{C-c M-s} searches the
+input history taking the current input as the query. @kbd{C-c M-r}
+searches backward while @kbd{C-c M-s} searches forward. And @kbd{C-c
+C-r} searches the input history using minibuffer with completion,
+useful specially if you use any minibuffer completion UI/framework.
+
+You can also use Isearch
+(@pxref{Incremental Search,,, emacs, GNU Emacs Manual}) to search
+through the input history, with @kbd{M-r}. You can also customize
+@code{eat-line-input-history-isearch} to use all standard Isearch
+commands to search the input history.
+
+@vindex eat-line-input-history-isearch
+@defopt eat-line-input-history-isearch
+Controls where Isearch searches in Eat buffer. If @code{t}, usual
+Isearch commands in Eat buffer search in the input history. If
+@code{dwim}, Isearch keys search in the input history only when
+initial point position is on input line. When starting Isearch from
+other parts of the Eat buffer, they search in the Eat buffer. If
+@code{nil}, Isearch operates on the whole Eat buffer.
+@end defopt
+
+Input history is not loaded from the shell history file, to do that,
+@xref{Line Mode Integration}.
+
+@node Password Input
+@cindex password input
+@cindex credential input
+@cindex input, password
+@cindex input, credential
+@chapter Password Input
+
+By default, every keystroke gets recorded in the lossage, which can be
+seen by pressing @kbd{C-h l}. This is actually a good thing, unless
+you're inputting password.
+
+@findex eat-send-command
+Emacs doesn't record keystrokes when a password is read from the
+minibuffer. However, when the password prompt is in the terminal, the
+keys you use to type in your password gets recorded. To prevent this
+from happening, you can use the command @command{eat-send-command},
+it'll read password from the minibuffer and send it. Since the
+password is read from the minibuffer, it's not recorded.
+
+@part Part III:@* Advanced Customizations
+
+@node Shell Integration
+@cindex shell integration
+@cindex integration, shell
+@chapter Shell Integration
+
+Eat comes with shell scripts to integrate your favorite shell with
+Eat. When shell integration is enabled and the script is loaded in
+your shell, it'll take care of everything and provide many useful
+features.
+
+Currently only GNU Bash and Zsh are supported.
+
+If you use GNU Bash, put the following in your @samp{.bashrc} file:
+
+@example
+[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
+ source "$EAT_SHELL_INTEGRATION_DIR/bash"
+@end example
+
+If you use Zsh, put the following in your @samp{.zshrc} file:
+
+@example
+[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && \
+ source "$EAT_SHELL_INTEGRATION_DIR/zsh"
+@end example
+
+@anchor{Directory tracking}
+@cindex directory tracking
+@cindex tracking directory
+@cindex working directory tracking
+@cindex tracking working directory
+@cindex cwd tracking
+@cindex tracking cwd
+@section Directory tracking
+After you've setup shell integration, the Eat will track the working
+directory of your shell. That means @command{find-file} will start
+from your shell's current working directory. This also works in
+Eshell, but after the program exits, the current working directory is
+changed back to the directory from where the program was invoked.
+
+@vindex eat-enable-directory-tracking
+@defopt eat-enable-directory-tracking
+This controls directory tracking. When set to non-@code{nil}, Eat
+tracks the current working directory of programs.
+@end defopt
+
+@anchor{Shell Prompt Navigation}
+@cindex shell prompt navigation
+@cindex shell navigation, shell prompt
+@cindex prompt navigation
+@cindex navigation, prompt
+@section Shell Prompt Navigation
+@kindex C-c C-p @r{(``emacs mode''})
+@kindex C-c C-p @r{(``semi-char mode'')}
+@findex eat-previous-shell-prompt
+@kindex C-c C-n @r{(``emacs mode'')}
+@kindex C-c C-n @r{(``semi-char mode'')}
+@findex eat-next-shell-prompt
+You can navigate shell prompts in ``emacs'' and ``semi-char'' mode.
+@kbd{C-c C-p}, bound to @command{eat-previous-shell-prompt}, goes to
+the previous shell prompt. @kbd{C-c C-n}, bound to
+@command{eat-next-shell-prompt}, is the opposite, it goes to the next
+shell prompt. This doesn't work in Eshell.
+
+@cindex narrow to shell prompt
+@cindex narrow to prompt
+@cindex narrow, shell prompt
+@cindex narrow, prompt
+@kindex C-x n d @r{(``emacs mode'')}
+@kindex C-x n d @r{(``semi-char mode'')}
+@findex eat-narrow-to-shell-prompt
+You can narrow (@pxref{Narrowing,,, emacs, GNU Emacs Manual}) down Eat
+buffer to a shell prompt and its output (if any) using the key
+sequence @kbd{C-x n d}, bound to @command{eat-narrow-to-shell-prompt}.
+
+@anchor{Shell Prompt Annotation}
+@cindex shell prompt annotation
+@cindex annotation, shell prompt
+@cindex annotate, shell prompt
+@cindex prompt annotation
+@cindex annotation, prompt
+@cindex annotate, prompt
+@section Shell Prompt Annotation
+When shell integration is setup, Eat annotates each shell prompt. Eat
+puts a mark on the shell prompt indicating the whether the command
+entered in that prompt is running, exited successfully or exited with
+non-zero status. This doesn't work in Eshell. You can disable this
+feature if you want.
+
+@vindex eat-enable-shell-prompt-annotation
+@defopt eat-enable-shell-prompt-annotation
+This controls shell prompt annotation by Eat. When set to
+non-@code{nil}, Eat annotates shell prompts to indicate the status of
+the command entered in that prompt.
+@end defopt
+
+Eat uses the marginal area
+(@pxref{Display Margins,,, elisp, GNU Emacs Lisp Reference Manual}) on
+the left side to display the annotation. You also use the right
+margin.
+
+@vindex eat-shell-prompt-annotation-position
+@defopt eat-shell-prompt-annotation-position
+This controls where the shell prompt annotations are displayed. When
+set to @code{left-margin} (the default), Eat uses the left margin.
+When set to @code{right-margin}, Eat uses the right margin.
+@end defopt
+
+@vindex eat-shell-prompt-annotation-running-margin-indicator
+@vindex eat-shell-prompt-annotation-running
+@vindex eat-shell-prompt-annotation-success-margin-indicator
+@vindex eat-shell-prompt-annotation-success
+@vindex eat-shell-prompt-annotation-failure-margin-indicator
+@vindex eat-shell-prompt-annotation-failure
+Eat uses the strings ``-'', ``0'' and ``X'' respectively to indicate
+the command is running, the command has succeeded and the command has
+failed. You can also customize the them. The user option
+@code{eat-shell-prompt-annotation-running-margin-indicator} and the
+face @code{eat-shell-prompt-annotation-running} control the indicator
+used to indicate the command is running. The user option
+@code{eat-shell-prompt-annotation-success-margin-indicator} and the
+face @code{eat-shell-prompt-annotation-success} control the indicator
+used to indicate the command has exited successfully. And finally
+the user option
+@code{eat-shell-prompt-annotation-failure-margin-indicator} and the
+face @code{eat-shell-prompt-annotation-failure} control the indicator
+used to indicate the command has exited unsuccessfully with non-zero
+exit status.
+
+@anchor{Message Passing}
+@section Message Passing
+
+After enabling shell integration, you can send messages to Emacs from
+your shell. Then you can handle the message on Emacs side using usual
+Emacs Lisp function.
+
+When shell integration script is loaded, a function named
+@command{_eat_msg} is defined in your shell. You can use this to send
+any message to Emacs. (The @samp{_} in the beginning of the function
+name is intentional to prevent shadowing any actual command.)
+
+@deffn Command _eat_msg @var{handler-name} @var{message}...
+Send message @var{message}, handled by the handler named
+@var{handler-name} in Emacs.
+@end deffn
+
+The messages are handled with the handlers defined in
+@code{eat-message-handler-alist}.
+
+@vindex eat-message-handler-alist
+@defopt eat-message-handler-alist
+Alist of message handler name and its handler function. The keys are
+the names of message handlers (i.e. the @var{handler-name} argument of
+@command{_eat_msg}), and the values are their respective handler
+functions. The handler function is called with the @var{message}
+arguments of @command{_eat_msg}. Messages with undefined handlers are
+ignored. To disable message passing, set this to nil.
+@end defopt
+
+Beware, messages can be sent by malicious and/or buggy programs
+running in the shell, therefore you should always verify the message
+before doing anywhere.
+
+@anchor{Line Mode Integration}
+@cindex line mode integration
+@cindex line mode shell integration
+@cindex integration, shell, line mode
+@section Line Mode Integration
+
+When shell integration is enabled, the input history of line mode is
+automatically filled with the shell history when the shell starts.
+Also you can make Eat automatically switch to ``line mode''
+(@pxref{Line Mode}) for you when the shell prompt appears.
+
+@vindex eat-enable-auto-line-mode
+@defopt eat-enable-auto-line-mode
+When non-nil, automatically switch to line mode the shell prompt
+appears.
+@end defopt
+
+@node Querying Before Kill
+@cindex querying before kill
+@cindex querying before kill terminal
+@cindex confirm before kill
+@cindex confirm before kill terminal
+@cindex terminal, kill, query
+@cindex terminal, kill, confirm
+@chapter Querying Before Kill
+
+When a terminal is killed, the terminal process is also killed. Since
+the process can do some important things, Eat asks for confirmation
+before killing a terminal with running process by default. Eat
+provides the user option
+@code{eat-query-before-killing-running-terminal} to control this.
+
+@vindex eat-query-before-killing-running-terminal
+@defopt eat-query-before-killing-running-terminal
+When set to @code{nil}, Eat would never ask. When set to @code{t},
+Eat would always ask for confirmation. When set to @code{auto}, Eat
+would ask only if a shell command is running inside the shell running
+in the terminal. This is effective only after shell integration is
+enabled in the shell (@pxref{Shell Integration}) (i.e. after the shell
+integration code is executed on shell); before that it is essentially
+same as @code{t}, and Eat will always query.
+@end defopt
+
+@node Display
+@cindex display
+@chapter Display
+
+Display is the region you see on the terminal. The program writes to
+the display and manipulates the text on the display. The display can
+be of any size. The cursor is always on the display (though it might
+be invisible sometimes, @pxref{Cursor Types}).
+
+@vindex window-adjust-process-window-size-function
+You can resize the display by resizing the terminal window. The
+display size is controlled by the Emacs user option
+@code{window-adjust-process-window-size-function}. @xref{Process
+Buffers,,, elisp, GNU Emacs Lisp Reference Manual} for the possible
+values of the user option.
+
+@node Scrollback
+@cindex scrollback
+@chapter Scrollback
+
+When you go too downward on the terminal, the terminal starts to
+``scroll''. This causes the line at the upper side of the terminal to
+go out of the display and become hidden. But these line are not
+deleted, they are just put in the scrollback region.
+
+Scrollback region is a region just above the display of the terminal.
+This contains the lines that went out of display due to scrolling up.
+
+Scrollback region is not unlimited by default, to avoid using too much
+memory. You can change the limit, or remove it altogether.
+
+@vindex eat-term-scrollback-size
+@defopt eat-term-scrollback-size
+This controls the size of scrollback region. It is expressed in
+character. If set to @var{size}, Eat won't store more than @var{size}
+characters in the scrollback region. If set to @code{nil}, the
+scrollback region is unlimited.
+@end defopt
+
+@node Cursor Types
+@cindex cursor types
+@cindex types, cursor
+@cindex changing cursor
+@cindex customizing cursor
+@cindex cursor blinking
+@cindex blinking cursor
+@chapter Cursor Types
+
+In terminal, cursor can be of up to three type: ``visible'',
+``invisible'' and ``very visible''. ``Visible'' is the default cursor
+type, which is the cursor you usually see in a shell (unless the shell
+changes the cursor type). ``Invisible'' is, as the name suggests,
+invisible, you can't see it. ``Very visible'' cursor is a blinking
+cursor, programs use this to help you not lose the cursor.
+
+The cursor type can customized with three user options for the three
+types of cursor. Each of the user options share the same format.
+
+@vindex eat-default-cursor-type
+@defopt eat-default-cursor-type
+This controls the cursor shape of the ``visible'' cursor type.
+@end defopt
+
+@vindex eat-invisible-cursor-type
+@defopt eat-invisible-cursor-type
+This controls the cursor shape of the ``invisible'' cursor type.
+@end defopt
+
+@vindex eat-very-visible-cursor-type
+@defopt eat-very-visible-cursor-type
+This controls the cursor shape of the ``very visible'' cursor type.
+This cursor blinks, switching between the default cursor shape and a
+hollow box.
+@end defopt
+
+@vindex eat-vertical-bar-cursor-type
+@defopt eat-vertical-bar-cursor-type
+This controls the cursor shape of the ``vertical bar'' cursor type.
+@end defopt
+
+@vindex eat-very-visible-vertical-bar-cursor-type
+@defopt eat-very-visible-vertical-bar-cursor-type
+This controls the cursor shape of the ``very visible vertical bar''
+cursor type. This cursor blinks.
+@end defopt
+
+@vindex eat-horizontal-bar-cursor-type
+@defopt eat-horizontal-bar-cursor-type
+This controls the cursor shape of the ``horizontal bar'' cursor type.
+@end defopt
+
+@vindex eat-very-visible-horizontal-bar-cursor-type
+@defopt eat-very-visible-horizontal-bar-cursor-type
+This controls the cursor shape of the ``very visible horizontal bar''
+cursor type. This cursor blinks.
+@end defopt
+
+The value type of all these user options is a list. The list is of
+form (@var{cursor-on} @var{blinking-frequency} @var{cursor-off}).
+@var{blinking-frequency} is the frequency of blinking of cursor. It
+is a number, controlling how many times the cursor will blink a
+second. This can also be @code{nil}, this will disable cursor
+blinking. @var{cursor-on} is the default cursor shape, only this
+shape is shown on the display when blinking is disabled. This uses
+the same format as Emacs's @code{cursor-type} user option
+(@pxref{Cursor Display,,, emacs, GNU Emacs Manual}). When
+@var{blinking-frequency} is a number, Eat will consult to the third
+element of the list, @var{cursor-off}, whose format same as
+@var{cursor-on}. The blinking cursor switches between @var{cursor-on}
+and @var{cursor-off} cursor shape.
+
+@node Mouse Tracking
+@cindex mouse tracking
+@cindex tracking mouse
+@chapter Mouse Tracking
+
+Eat tracks mouse by default, when the program supports mouse. But
+sometimes, you may want to avoid using mouse, or you might not have a
+mouse at all. So mouse tracking can be toggled.
+
+@vindex eat-enable-mouse
+@defopt eat-enable-mouse
+This user option controls mouse tracking. When set to non-@code{nil},
+mouse tracking is enabled. Set to this to @code{nil} to disable mouse
+tracking. This is enabled by default.
+@end defopt
+
+@node Clipboard
+@cindex clipboard
+@chapter Clipboard
+
+@cindex yanking
+@findex eat-yank
+@kindex C-y @r{(``semi-char mode'')}
+@findex eat-yank-pop
+@kindex M-y @r{(``semi-char mode'')}
+Just like any other buffer, you can yank text in terminal with
+@kbd{C-y} (bound to @command{eat-yank}) or @kbd{M-y} (bound to
+@command{eat-yank-pop}) in ``semi-char mode''.
+
+@cindex clipboard integration
+Programs can also request to the terminal to kill (@pxref{Killing,,,
+emacs, GNU Emacs Manual}) something. It is up to Eat whether the
+request will be fulfilled or not. By default, Eat fulfills the
+request and kills the text. This can sometimes be annoying, when the
+program automatically kills text without user interaction. This
+killing can be configured with the following user option:
+
+@vindex eat-enable-kill-from-terminal
+@defopt eat-enable-kill-from-terminal
+This controls killing texts from terminal. When set to
+non-@code{nil}, killing something from terminal add the text to
+Emacs's kill ring (@pxref{Kill Ring,,, emacs, GNU Emacs Manual}).
+This is enabled by default.
+@end defopt
+
+Programs can also request the text in kill ring. Again, this is up to
+Eat whether the request will be fulfilled or not. You can customize
+the following user option to configure this:
+
+@vindex eat-enable-yank-to-terminal
+@defopt eat-enable-yank-to-terminal
+This controls sending kill ring texts to terminal. When set to
+non-@code{nil}, programs can receive the kill ring contents. This is
+disabled by default for security reasons.
+@end defopt
+
+@node Colors
+@cindex colors
+@cindex customizing colors
+@chapter Colors
+
+Eat can show more than 16 million colors (16,777,216 colors exactly).
+Eat has also a palette of 256 colors, which is more than enough for
+most applications. Programs usually use this color palette. Each of
+these 256 colors can customized.
+
+There are 256 faces for the 256 colors, one face for each color. They
+are named like @code{eat-term-color-@var{n}}, which corresponds to
+color @var{n}, and @var{n} can be any number between 0 and 255
+(inclusive). For example, color 42 is can be changed by customizing
+@code{eat-term-color-42}.
+
+The foreground attribute contains the color value to use for the
+corresponding color. Other attributes are currently ignored and
+reserved for future changes.
+
+@cindex color aliases
+@cindex face aliases
+@cindex aliases, face
+@cindex aliases, color
+Each of the first 16 colors, from @code{eat-term-color-0} to
+@code{eat-term-color-15} also have a alias. They are respectively
+@code{eat-term-color-black},
+@code{eat-term-color-red},
+@code{eat-term-color-green},
+@code{eat-term-color-yellow},
+@code{eat-term-color-blue},
+@code{eat-term-color-magenta},
+@code{eat-term-color-cyan},
+@code{eat-term-color-white},
+@code{eat-term-color-bright-black},
+@code{eat-term-color-bright-red},
+@code{eat-term-color-bright-green},
+@code{eat-term-color-bright-yellow},
+@code{eat-term-color-bright-blue},
+@code{eat-term-color-bright-magenta},
+@code{eat-term-color-bright-cyan}
+and @code{eat-term-color-bright-white}.
+
+Eat also supports 24-bit colors, or so called ``truecolor''. Programs
+like Emacs can give a RGB triplet to use as the color of some text.
+As the programs directly specify the color in this case, you can't
+customize these color. But you may configure the program sending the
+color codes.
+
+@cindex color advertisement
+@cindex advertising colors
+Eat doesn't always advertise color support depending on the display
+Eat is running. For example, if you are on a Linux console which
+supports only eight colors, Eat will advertise eight color support to
+the programs, while on graphical displays with 24-bit color support,
+Eat will report 24-bit color support. This is because Eat supports
+more colors, the display doesn't always support them.
+
+@vindex TERM
+@cindex @env{TERM} environment variable
+@cindex environment variable, @env{TERM}
+Eat does the trick by setting the @env{TERM} environment variable of
+the program. The value of @env{TERM} depends on the number of the
+available colors on the display. This environment variable is
+controlled by the following user option:
+
+@vindex eat-term-name
+@defopt eat-term-name
+The value of @env{TERM} environment variable as a string. The value
+can also be a function taking no arguments, that function should
+return a string which used as the value of @env{TERM}. The default
+value is @code{eat-term-get-suitable-term-name}, which is responsible
+for the behavior described above.
+@end defopt
+
+@node Fonts
+@cindex fonts
+@chapter Fonts
+
+Programs may request the terminal to change the text font. It can
+change text weight, use italic text, or even change the font family
+altogether.
+
+@cindex bold text
+@cindex text, bold
+@vindex eat-term-bold
+Programs may request the terminal to show some text bolder than
+normal. Bold text uses the face @code{eat-term-bold}.
+
+@cindex faint text
+@cindex text, faint
+@vindex eat-term-bold
+Programs may also request the terminal to show some text fainter than
+normal. Faint text uses the face @code{eat-term-faint}.
+
+@cindex italic text
+@cindex slant text
+@cindex text, italic
+@cindex text, slant
+@vindex eat-term-italic
+Programs may request the terminal to show italic text too. Italic
+text uses the customizable face @code{eat-term-italic}.
+
+@cindex font family
+@cindex text, font family
+The number of available fonts is ten. Most of the programs doesn't
+change the font. Following many other terminal emulator, Eat actually
+uses the same font, the default font, regardless of the font requested
+by the program, by default.
+
+@cindex customizing font families
+There are ten faces for ten fonts, one face for each. They are named
+like @code{eat-term-font-@var{n}}, which corresponds to color @var{n},
+and @var{n} can be any number between 0 and 9 (inclusive). For
+example, the font 6 is can be changed by customizing
+@code{eat-term-font-6}. Font 0 is the default font.
+
+@node Sixel
+@cindex sixel
+@chapter Sixel
+
+Eat can show Sixel graphics. Sixel is a bitmap graphics format that
+can be used to display graphics in a terminal, for example, images, or
+plotting graphs.
+
+You can control the display of Sixel images by customizing the
+following user options.
+
+@vindex eat-sixel-scale
+@defopt eat-sixel-scale
+This is a non-negative number that specifies the amount to scale the
+image by.
+@end defopt
+
+@vindex eat-sixel-aspect-ratio
+@defopt eat-sixel-aspect-ratio
+This is a non-negative number that specifies the aspect ratio, i.e.
+the ratio of width and height of a Sixel pixel. For example, the
+value of 2 means the width of a Sixel pixel is the double of its
+height.
+@end defopt
+
+Eat converts Sixel graphics to an image format Emacs can natively
+display. This preference of image formats can be configured by
+customizing the @code{eat-sixel-render-formats} user option.
+
+@vindex eat-sixel-render-formats
+@defopt eat-sixel-render-formats
+List of formats to render Sixel, in order of preference. Each element
+of the list is one of @code{xpm}, @code{svg}, @code{half-block},
+@code{background}, @code{none}. @code{xpm} and @code{svg} means to
+use XPM and SVG image format respectively, @code{half-block} means to
+use UTF-8 half block characters, @code{background} means to just use
+background color, and @code{none} means to not render the image,
+instead just clear the area.
+@end defopt
+
+@node Blinking Text
+@cindex blinking text
+@cindex text, blinking
+@chapter Blinking Text
+
+Programs can request the terminal to blink some text. This helps to
+get user attention. But however, often this annoying to many people
+and also has accessiblity problems. So this is disabled by default.
+
+@vindex eat-enable-blinking-text
+@defopt eat-enable-blinking-text
+This controls the blinking of text with blink attribute. When set to
+non-@code{nil}, Eat arranges that text with blink attribute will
+blink at a certain interval.
+@end defopt
+
+@findex eat-blink-mode
+You can toggle blinking temporarily by toggle the buffer-local minor
+mode @command{eat-blink-mode}. This is only effective in the buffer
+where the mode is toggled.
+
+By default, @code{eat-enable-blinking-text} is set to @code{nil}.
+This disables text blinking and causes the text with blink attribute
+to be displayed in inverse video (swapped foreground and background).
+
+@vindex eat-term-slow-blink
+@vindex eat-term-fast-blink
+Programs may also request to blink some text more rapidly that other
+blinking text. When blinking is disabled, the face
+@code{eat-term-slow-blink} is used for slowly blinking text, and
+@code{eat-term-fast-blink} for rapidly blinking text.
+
+When blinking is enabled, by setting @code{eat-enable-blinking-text}
+to non-@code{nil} value, the following user options can be customized
+to change the rate of blinking:
+
+@vindex eat-slow-blink-frequency
+@defopt eat-slow-blink-frequency
+The blinking rate of slowly blinking text. When set to a number N,
+it causes slowly blinking text to blink N times a second. The value
+can also be a floating point number. The default value is 2, meaning
+that the slowing text will blink two times a second.
+@end defopt
+
+@vindex eat-fast-blink-frequency
+@defopt eat-fast-blink-frequency
+The blinking rate of rapidly blinking text. When set to a number N,
+it causes rapidly blinking text to blink N times a second. The value
+can also be a floating point number as well. The default value is 3,
+meaning that the slowing text will blink three times a second.
+@end defopt
+
+@node Performance Tuning
+@cindex performance tuning
+@cindex tuning performance
+@chapter Performance Tuning
+
+Eat tries to be as fast as possible. So Eat employs some techniques
+to maximize performance.
+
+Some program choke and hang when given too much input at once. So Eat
+divides large input to smaller chunks and sends the chunks one at a
+time. The maximum size of a input chunk is controlled by
+@code{eat-input-chunk-size}.
+
+@vindex eat-input-chunk-size
+@defopt eat-input-chunk-size
+The value is a integer. Eat treat input larger than this many
+character as large and breaks it into chunks of at most this size
+before sending the input.
+@end defopt
+
+@cindex flickering
+@cindex reason behind flickering
+@cindex cause of flickering
+Programs also break large output into smaller chunks before sending
+it to the terminal, for same reason. Eat doesn't suffer from the
+problem, but there isn't any standard way to inform programs about
+this, and usually there are other obstructions sending large amount of
+data at once. These small chunks create another problem for Eat,
+flickering. When updating the whole display, the output is usually
+pretty large and the programs break them into smaller chunks. Each of
+the chunks update the display partially. After receiving the last
+chunk, the update is complete and the display can be updated. But it
+is impossible for Eat to guess the last chunk, so Eat has to redisplay
+or update the display after receiving each chunk. This is the reason
+why sometimes the terminal shows some old contents and some new. This
+only lasts for a fraction of a second until the next chunk is received
+and processed. This is flickering. This also degrades performance,
+because redisplay is an expensive process and takes some time.
+
+@cindex fixing flickering
+@cindex flickering fix
+@cindex latency
+Fixing the flickering completely is not possible. Eat tries to
+decrease flickering by deferring redisplay. After receiving a chunk,
+Eat waits for a tiny fraction of a second. If another chunk arrives
+within the time, the redisplay is postponed. Then Eat waits for the
+same amount of time and this goes on. When timeout occurs, Eat
+processing the output and displays the output. This causes a small
+latency between output arrive and redisplay, but this is usually not
+long enough for human eyes to catch it. This waiting time can be
+configured with the following user option:
+
+@vindex eat-minimum-latency
+@defopt eat-minimum-latency
+The value is the time in seconds to wait for the next chunk to arrive.
+This is the minimum latency between the first chunk after a redisplay
+and the next redisplay. For example, if you press @kbd{@key{RET}} in
+an empty Bash prompt, the next prompt won't appear before this much
+time.
+
+You should set the time to something comfortable for you. You can
+also set this to zero to disable waiting and showing the output
+instantly, but this would likely cause a lot of flickering.
+@end defopt
+
+However, this waiting raises another problem. What if you execute the
+POSIX command @samp{yes} in the terminal? It will write infinite
+``y''s in the terminal without any delay between them anywhere. Eat
+will wait indefinitely for a delay between two chunks, which will
+never happen, unless the program is executed remotely and the
+connection is slow enough. So Eat has a limit for waiting, the
+display will be always be updated after this time. This limit also
+customizable:
+
+@vindex eat-maximum-latency
+@defopt eat-maximum-latency
+The value is the time in seconds to wait at most for chunk. In case
+of large burst of output, redisplay is never deferred more than this
+many seconds, and cause a latency of up to this many seconds.
+
+You should set the time to something comfortable for you. You can
+also set this to zero to disable waiting and showing the output
+instantly, but this would likely cause a lot of flickering.
+@end defopt
+
+Due to some limitations, shell prompt annotations
+(@pxref{Shell Integration}) can get messed up sometimes. Eat
+automatically corrects them after each terminal redisplay. However,
+this can have some performance impact when the terminal scrollback and
+display is large enough (unless the buffer is narrowed). So Eat
+defers the correction.
+
+@vindex eat-shell-prompt-annotation-delay
+@defopt eat-shell-prompt-annotation-delay
+The value is the time in seconds to wait for more output before
+correcting shell prompt annotations.
+
+You should set the time to something comfortable for you. You can
+also set this to zero to disable waiting and correct annotations
+instantly, but this may cause the terminal to slow down in some cases.
+@end defopt
+
+The user options described in this chapter have reasonable default
+values, but the default values may change anytime.
+
+@part Part IV:@* Recovering from Problems
+
+@node Common Problems
+@cindex common problems
+@cindex problem, common
+@chapter Common Problems
+
+This chapter describe how to recognize and handle situations in which
+Eat does something unexpected, such as hangs, garbled text, etc.
+
+@menu
+* Not Recognized:: The program can't recognize Eat.
+* Garbled Text:: When you get garbage on your terminal.
+* Input Invisible:: The input is not shown.
+* Not Responding:: What to do if Eat is unresponsive.
+* Signaled an Error:: The worst and the most unlikely bug.
+* Bugs in Manual:: What if there are problems in this manual?
+@end menu
+
+@node Not Recognized
+@cindex not recognized
+@cindex problem, not recognized
+@cindex terminal not recognized
+@cindex problem, terminal not recognized
+@section Terminal Not Recognized
+
+If your program says that it can't recognize the terminal, probably
+the @env{TERM} environment variable has a wrong value.
+
+@vindex eat-term-name
+Check the value of @env{TERM}, if it's not set to something like
+@samp{eat-...}, check the user option @code{eat-term-name}. If that's
+correct that your shell might be changing the @env{TERM} environment
+variable. If @code{eat-term-name} isn't correct, customize to a
+suitable value and try again, your problem should be fixed.
+
+@vindex eat-term-terminfo-directory
+If @env{TERM} has the correct value, then probably the Terminfo
+databases of Eat are missing. This can happen if you have installed
+Eat without using the package from NonGNU ELPA
+(@pxref{Packages,,, emacs, GNU Emacs Manual}). Check that whether
+the values of the environment variable @env{TERMINFO} and the user
+option @code{eat-term-terminfo-directory} match. If they match,
+customize @code{eat-term-terminfo-directory} to the directory
+containing the Terminfo databases, the program should now recognize
+Eat. If they don't match, then your shell is probably responsible for
+the problem.
+
+@findex eat-compile-terminfo
+If the program is not recognizing the terminal even when
+the correct directory is set as @code{eat-term-terminfo-directory},
+probably the precompiled Terminfo databases aren't working properly on
+your system. You can invoke the command
+@command{eat-compile-terminfo} to recompile it for your system.
+
+If you can't find the directory containing Terminfo databases, you can
+compile it yourself. First, set @code{eat-term-terminfo-directory} to
+the directory where to put the Terminfo databases. Then invoke the
+command @command{eat-compile-terminfo} to compile the Terminfo
+databases.
+
+@node Garbled Text
+@cindex garbled text
+@cindex problem, garbled text
+@cindex problem, text garbled
+@section Garbled Text on Terminal
+
+If the text on the terminal looks wrong, first check out the value of
+@env{TERM}. Usually @env{TERM} has a wrong value set, making programs
+send invalid escape sequences.
+
+First, @pxref{Not Recognized}; the problem is most likely because the
+program doesn't recognize Eat, and it stays silent instead of
+reporting that.
+
+If the problem isn't resolved after following the instructions in the
+previous section, probably the precompiled Terminfo databases aren't
+working properly on your system. Running the command
+@command{eat-compile-terminfo} will recompile it for your system.
+
+If the problem still persists, may be your program is blindly assuming
+that the terminal is XTerm-compatible. If so, what you are seeing is
+the current state of ``XTerm-compliance''. Though it's not really a
+bug, we really want to know what's problem so that we can fix it and
+improve XTerm-compliance. @xref{Reporting Bugs} for instructions on
+sending bug reports or feature request.
+
+The other potential reason is that Eat is not working. This is
+definitely a bug, so please report it.
+
+@node Input Invisible
+@cindex input invisible
+@cindex input, invisible
+@cindex invisible input
+@cindex invisible, input
+@section Input Invisible
+
+This can happen if the @samp{stty} program is unavailable on the
+system. Eat uses @samp{stty} to set various terminal settings
+including input echoing. Please install the @samp{stty} program to
+fix the problem.
+
+@vindex eat-eshell-fallback-if-stty-not-available
+If you are using Eat from Eshell (@pxref{Eshell Terminal}), you might
+want to set @code{eat-eshell-fallback-if-stty-not-available} to handle
+such cases. The user option can be set to three possible value,
+@code{t} to automatically fallback to bare Eshell when @samp{stty} is
+not available, @code{nil} to do nothing, and @samp{ask} to ask
+interactively.
+
+@node Not Responding
+@cindex not responding, eat
+@cindex not responding, emacs
+@cindex eat not responding
+@cindex emacs not responding
+@cindex problem, eat not responding
+@cindex problem, emacs not responding
+@cindex problem, not responding, eat
+@cindex problem, not responding, emacs
+@section Emacs or Eat Not Responding
+
+If you run something that outputs huge amount of data, your Emacs may
+not respond, and even quitting may not work. Quitting doesn't work
+while doing something terminal related (output processing, for
+example), and that's intentional, because quitting would mess up the
+terminal.
+
+The best way to fix it is to stop the program, so that Eat is not
+overloaded. To avoid the problem in future, it is recommended to run
+those programs in faster terminals like bare Eshell (i.e. without
+Eat-Eshell), Comint, or external terminal emulators.
+
+@node Signaled an Error
+@cindex signaled an error
+@cindex eat signaled an error
+@cindex problem, signaled an error
+@cindex problem, eat signaled an error
+@section Eat Signaled an Error
+
+The worst thing that happen is that Eat might signal an error. It is
+the worst thing possible, because it messes up the terminal, and also
+a security hole. Fortunately, this is very rare. If you ever find
+any such bug, you should report the bug (@pxref{Reporting Bugs}) as
+soon as possible with as much information as possible.
+
+@findex eat-reset
+Once the error signaled, your best option is to delete the terminal
+and start a new one. But if you don't want to delete the terminal,
+you can try invoking the command @command{reset} from your shell. If
+for some reason you can't do that, invoke the Emacs command
+@command{eat-reset}. This will reset most of the terminal state and
+give you a clean terminal to work with. However, it mayn't work if
+you're really unlucky, in that case deleting the terminal and starting
+a new one is your only option.
+
+@node Bugs in Manual
+@cindex bugs in manual
+@cindex typos in manual
+@cindex bugs, manual
+@cindex typos, manual
+@cindex manual, bugs
+@cindex manual, typos
+@cindex problems, bugs in manual
+@cindex problems, typos in manual
+@cindex problems, bugs, manual
+@cindex problems, typos, manual
+@cindex problems, manual, bugs
+@cindex problems, manual, typos
+@section Bugs in Manual
+
+Human makes mistake, and we are no exceptions. But we are trying hard
+to improve Eat and it's manual.
+
+If you don't understand something even after a careful rereading,
+that's a bug.
+
+If you find anything unclear in this manual, that's a bug.
+
+This manual's job is make everything clear, so failing to do that
+indicates a bug.
+
+If the built-in documentation and this manual don't agree, one of them
+must be wrong, and that's a bug.
+
+If you Eat doesn't behave as this manual describes, that's a bug.
+
+If you find any typing mistakes, that's a bug.
+
+If you find a bug, please report it. @xref{Reporting Bugs} for
+instruction on how to report it.
+
+@node Reporting Bugs
+@cindex reporting bugs
+@cindex bug reporting
+@cindex problem, reporting
+@chapter Reporting Bugs
+
+We welcome bug reports and feature request. If you think you have
+found a bug, please report it. If you're doubt, please send it
+anyway. We can't promise that we'll fix the bug or implement your
+feature idea, or always agree that it's a bug, but we always want to
+hear from you. Please report bugs at
+@url{https://codeberg.org/akib/emacs-eat/issues/}. You may send the
+bug report by emailing to the maintainer
+(@kbd{M-x describe-package @key{RET} eat @key{RET}} would show the
+email address), but we prefer the former method, since the report is
+visible to everyone immediately.
+
+The most important principle in reporting a bug is to report
+@emph{facts}. Hypotheses and verbal descriptions are useful when they
+are more guesses, but in no way substitute for detailed raw data. You
+are encouraged to send you finding about bug, but please make sure to
+send the raw data needed to reproduce the bug.
+
+For bug reports, please try to reproduce the bug with @samp{emacs -Q}.
+This will disable loading your Emacs configuration, ruling out the
+potential bugs in your customizations. Please include enough
+information for us to reproduce the bug with @samp{emacs -Q}, so that
+we have (or can get) enough information about the bug to fix it. Some
+bugs are hard to reproduce with @samp{emacs -Q}, and some are not
+easily reproducible at all, in that case please give us the as much
+information as possible about Emacs configuration. Generally
+speaking, enough information includes (but not limited to):
+
+@itemize @bullet
+@item
+A description of the bug.
+
+@item
+The version of Eat you're running.
+(@kbd{M-x describe-package RET eat RET} would show the version.)
+
+@item
+The version of Emacs you're running.
+
+@item
+Your Eat configuration, precisely.
+
+@item
+If you didn't or can't reproduce the bug with @code{emacs -Q}, as much
+information as possible about Emacs configuration.
+
+@item
+Precisely what you did.
+
+@item
+Trace output, if you can generate it. (@xref{Tracing the Terminal}
+for instruction to generate it.)
+
+@item
+Hardware and operating system names and versions.
+
+@item
+Anything else that you think would be helpful.
+@end itemize
+
+When in doubt whether to include something or not, please include it.
+It is better to include many useless information than to leave out
+something useful.
+
+It is critical to send enough information to reproduce the bug. What
+is not critical to ``narrow down'' the example to the smallest
+possible -- anything that reproduces the bug will suffice. (Of
+course, if you like doing experiments, the smaller the example, the
+better.)
+
+@node Tracing the Terminal
+@cindex tracing the terminal
+@cindex terminal tracing
+@cindex terminal recording
+@chapter Tracing the Terminal
+
+When you run into a bug and want to report it, you'll want to trace
+the terminal. Tracing means recording all the terminal activity,
+including creation, output, resizing and deleting.
+
+@findex eat-trace-mode
+To enable tracing, enable the global minor mode
+@command{eat-trace-mode}. This will trace all new terminals,
+including the terminal created inside Eshell.
+
+Trace output for each command will be output in a buffer named
+@samp{*eat-trace @var{buffer-name}*: @var{command}}, where
+@var{buffer-name} is the buffer showing the terminal, and
+@var{command} is the command run in the terminal.
+
+Only the terminals created after the trace mode is enabled are traced.
+So if you don't have the mode enabled when you have found a bug,
+tracing can't give you any information (as tracing is disabled,
+nothing has been recorded).
+
+While submitting bug reports, please include the whole output in the
+trace output buffer. This contains many crucial information required
+to reproduce your bug.
+
+@findex eat-trace-replay
+You can replay the terminal by executing the command
+@command{eat-trace-replay} is the trace output buffer. You can use
+the key @kbd{n} or the key @kbd{@key{down}} to show the next frame.
+This is not intended for ordinary users, it's documented here only to
+help you debug Eat. You mustn't rely on the behavior of this
+functionality to do anything else.
+
+@part Part V:@* Appendices
+
+@node GNU General Public License
+@appendix GNU General Public License
+
+@include gpl.texi
+
+@node GNU Free Documentation License
+@appendix GNU Free Documentation License
+
+@include fdl.texi
+
+@node Index
+@appendix Index
+
+@printindex cp
+
+@bye
--- /dev/null
+# The code here is forced by the interface, and is not subject to
+# copyright, constituting the only possible expression of the
+# algorithm in this format.
+#
+# When updating this file, files in e/ should be regenerated by
+# running in "make" or "make terminfo" here.
+
+eat-mono|Emacs Eat without colors,
+ cols#80,
+ lines#24,
+ am,
+ clear=\e[2J,
+ cr=\r,
+ bel=^G,
+ home=\e[H,
+ cub1=\b,
+ cuf1=\e[C,
+ cuu1=\e[A,
+ cud1=^K,
+ ind=\n,
+ indn=\e[%p1%dS,
+ ri=\eM,
+ rin=\e[%p1%dT,
+ nel=\eE,
+ cup=\e[%i%p1%d;%p2%dH,
+ hpa=\e[%i%p1%dG,
+ vpa=\e[%i%p1%dd,
+ cub=\e[%p1%dD,
+ cuf=\e[%p1%dC,
+ cuu=\e[%p1%dA,
+ cud=\e[%p1%dB,
+ smcup=\e[?1049h,
+ rmcup=\e[?1049l,
+ el=\e[K,
+ el1=\e[1K,
+ ed=\e[J,
+ il1=\e[L,
+ il=\e[%p1%dL,
+ dl1=\e[M,
+ dl=\e[%p1%dM,
+ csr=\e[%i%p1%d;%p2%dr,
+ sc=\e7,
+ rc=\e8,
+ smir=\e[4h,
+ rmir=\e[4l,
+# ich1=\e[@,
+ ich=\e[%p1%d@,
+ mir,
+ dch1=\e[P,
+ dch=\e[%p1%dP,
+ ech=\e[%p1%dX,
+ smso=\e[7m,
+ rmso=\e[27m,
+ smul=\e[4m,
+ rmul=\e[24m,
+ sitm=\e[3m,
+ ritm=\e[23m,
+ blink=\e[5m,
+ bold=\e[1m,
+ dim=\e[2m,
+ invis=\e[8m,
+ rev=\e[7m,
+ sgr0=\e(B\e[m,
+ sgr=%?%p9%t\e(0%e\e(B%;
+ \e[0%?%p6%t;1%;
+ %?%p5%t;2%;
+ %?%p2%t;4%;
+ %?%p1%p3%|%t;7%;
+ %?%p4%t;5%;
+ %?%p7%t;8%;m,
+ msgr,
+ cvvis=\e[?12;25h,
+ civis=\e[?25l,
+ cnorm=\e[?12l\e[?25h,
+ smkx=\e[?1h,
+ rmkx=\e[?1l,
+ ht=\t,
+ cbt=\e[Z,
+ it#8,
+ rs1=\e\\\ec,
+ hs,
+ tsl=\e]2;,
+ fsl=\e\\,
+ dsl=\e]2;\e\\,
+ xenl,
+ acsc=++\,\,--..00``aaffggiihhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+ smacs=\e(0,
+ rmacs=\e(B,
+ npc,
+ rep=%p1%c\E[%p2%{1}%-%db,
+ u6=\e[%i%d;%dR,
+ u7=\e[6n,
+ smam=\e[?7h,
+ rmam=\e[?7l,
+ smxx=\e[9m,
+ rmxx=\e[29m,
+ kcbt=\E[Z,
+ kbs=^?,
+ kcuu1=\eOA,
+ kri=\e[1;2A,
+ kcud1=\eOB,
+ kind=\e[1;2B,
+ kcuf1=\eOC,
+ kRIT=\e[1;2C,
+ kcub1=\eOD,
+ kLFT=\e[1;2D,
+ kich1=\e[2~,
+ kIC=\e[2;2~,
+ kdch1=\e[3~,
+ kDC=\e[3;2~,
+ khome=\eOH,
+ kHOM=\e[1;2H,
+ kend=\eOF,
+ kEND=\e[1;2F,
+ kpp=\e[5~,
+ kPRV=\e[5;2~,
+ knp=\e[6~,
+ kNXT=\e[6;2~,
+ kf1=\eOP,
+ kf2=\eOQ,
+ kf3=\eOR,
+ kf4=\eOS,
+ kf5=\e[15~,
+ kf6=\e[17~,
+ kf7=\e[18~,
+ kf8=\e[19~,
+ kf9=\e[20~,
+ kf10=\e[21~,
+ kf11=\e[23~,
+ kf12=\e[24~,
+ kf13=\e[1;2P,
+ kf14=\e[1;2Q,
+ kf15=\e[1;2R,
+ kf16=\e[1;2S,
+ kf17=\e[15;2~,
+ kf18=\e[17;2~,
+ kf19=\e[18;2~,
+ kf20=\e[19;2~,
+ kf21=\e[20;2~,
+ kf22=\e[21;2~,
+ kf23=\e[23;2~,
+ kf24=\e[24;2~,
+ kf25=\e[1;5P,
+ kf26=\e[1;5Q,
+ kf27=\e[1;5R,
+ kf28=\e[1;5S,
+ kf29=\e[15;5~,
+ kf30=\e[17;5~,
+ kf31=\e[18;5~,
+ kf32=\e[19;5~,
+ kf33=\e[20;5~,
+ kf34=\e[21;5~,
+ kf35=\e[23;5~,
+ kf36=\e[24;5~,
+ kf37=\e[1;6P,
+ kf38=\e[1;6Q,
+ kf39=\e[1;6R,
+ kf40=\e[1;6S,
+ kf41=\e[15;6~,
+ kf42=\e[17;6~,
+ kf43=\e[18;6~,
+ kf44=\e[19;6~,
+ kf45=\e[20;6~,
+ kf46=\e[21;6~,
+ kf47=\e[23;6~,
+ kf48=\e[24;6~,
+ kf49=\e[1;3P,
+ kf50=\e[1;3Q,
+ kf51=\e[1;3R,
+ kf52=\e[1;3S,
+ kf53=\e[15;3~,
+ kf54=\e[17;3~,
+ kf55=\e[18;3~,
+ kf56=\e[19;3~,
+ kf57=\e[20;3~,
+ kf58=\e[21;3~,
+ kf59=\e[23;3~,
+ kf60=\e[24;3~,
+ kf61=\e[1;4P,
+ kf62=\e[1;4Q,
+ kf63=\e[1;4R,
+ kmous=\e[M,
+
+eat-color|Emacs Eat with eight colors,
+ use=eat-mono,
+ colors#0x8,
+ pairs#0x40,
+ bce,
+ op=\e[39;49m,
+ setab=\e[4%p1%dm,
+ setaf=\e[3%p1%dm,
+ setb=\e[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
+ setf=\e[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
+
+eat-256color|Emacs Eat with 256 colors,
+ use=eat-color,
+ colors#0x100,
+ pairs#0x10000,
+ setab=\e[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
+ setaf=\e[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
+ setb@,
+ setf@,
+
+eat-truecolor|Emacs Eat with truecolor,
+ use=eat-256color,
+ Tc,
--- /dev/null
+@c The GNU Free Documentation License.
+@center Version 1.3, 3 November 2008
+
+@c This file is intended to be included within another document,
+@c hence no sectioning command or @node.
+
+@display
+Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
+@uref{https://fsf.org/}
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense. It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does. But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book. We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The ``Document'', below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as ``you''. You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject. (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.) The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters. A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, La@TeX{} input
+format, SGML or XML using a publicly available
+DTD, and standard-conforming simple HTML,
+PostScript or PDF designed for human modification. Examples
+of transparent image formats include PNG, XCF and
+JPG@. Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, SGML or
+XML for which the DTD and/or processing tools are
+not generally available, and the machine-generated HTML,
+PostScript or PDF produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page. For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+The ``publisher'' means any person or entity that distributes copies
+of the Document to the public.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License. You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute. However, you may accept
+compensation in exchange for copies. If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover. Both covers must also clearly and legibly identify
+you as the publisher of these copies. The front cover must present
+the full title with all words of the title equally prominent and
+visible. You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it. In addition, you must do these things in the Modified Version:
+
+@enumerate A
+@item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document). You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+@item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+@item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+@item
+Preserve all the copyright notices of the Document.
+
+@item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+@item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+@item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+@item
+Include an unaltered copy of this License.
+
+@item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page. If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+@item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on. These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+@item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+@item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles. Section numbers
+or the equivalent are not considered part of the section titles.
+
+@item
+Delete any section Entitled ``Endorsements''. Such a section
+may not be included in the Modified Version.
+
+@item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
+@end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant. To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version. Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity. If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy. If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''. You must delete all
+sections Entitled ``Endorsements.''
+
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections. You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense, or distribute it is void, and
+will automatically terminate your rights under this License.
+
+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, receipt of a copy of some or all of the same material does
+not give you any rights to use it.
+
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation 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. See
+@uref{https://www.gnu.org/licenses/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation. If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation. If the Document
+specifies that a proxy can decide which future versions of this
+License can be used, that proxy's public statement of acceptance of a
+version permanently authorizes you to choose that version for the
+Document.
+
+@item
+RELICENSING
+
+``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any
+World Wide Web server that publishes copyrightable works and also
+provides prominent facilities for anybody to edit those works. A
+public wiki that anybody can edit is an example of such a server. A
+``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the
+site means any set of copyrightable works thus published on the MMC
+site.
+
+``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0
+license published by Creative Commons Corporation, a not-for-profit
+corporation with a principal place of business in San Francisco,
+California, as well as future copyleft versions of that license
+published by that same organization.
+
+``Incorporate'' means to publish or republish a Document, in whole or
+in part, as part of another Document.
+
+An MMC is ``eligible for relicensing'' if it is licensed under this
+License, and if all works that were first published under this License
+somewhere other than this MMC, and subsequently incorporated in whole
+or in part into the MMC, (1) had no cover texts or invariant sections,
+and (2) were thus incorporated prior to November 1, 2008.
+
+The operator of an MMC Site may republish an MMC contained in the site
+under CC-BY-SA on the same site at any time before August 1, 2009,
+provided the MMC is eligible for relicensing.
+
+@end enumerate
+
+@page
+@heading ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+ Copyright (C) @var{year} @var{your name}.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license is included in the section entitled ``GNU
+ Free Documentation License''.
+@end group
+@end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with@dots{}Texts.''@: line with this:
+
+@smallexample
+@group
+ with the Invariant Sections being @var{list their titles}, with
+ the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+ being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+@c Local Variables:
+@c ispell-local-pdict: "ispell-dict"
+@c End:
--- /dev/null
+@c The GNU General Public License.
+@center Version 3, 29 June 2007
+
+@c This file is intended to be included within another document,
+@c hence no sectioning command or @node.
+
+@display
+Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{https://fsf.org/}
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+@end display
+
+@heading 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.
+
+@heading TERMS AND CONDITIONS
+
+@enumerate 0
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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:
+
+@enumerate a
+@item
+The work must carry prominent notices stating that you modified it,
+and giving a relevant date.
+
+@item
+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''.
+
+@item
+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.
+
+@item
+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.
+@end enumerate
+
+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.
+
+@item 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:
+
+@enumerate a
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@end enumerate
+
+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.
+
+@item 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:
+
+@enumerate a
+@item
+Disclaiming warranty or limiting liability differently from the terms
+of sections 15 and 16 of this License; or
+
+@item
+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
+
+@item
+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
+
+@item
+Limiting the use for publicity purposes of names of licensors or
+authors of the material; or
+
+@item
+Declining to grant rights under trademark law for use of some trade
+names, trademarks, or service marks; or
+
+@item
+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.
+@end enumerate
+
+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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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.
+
+@item 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 enumerate
+
+@heading END OF TERMS AND CONDITIONS
+
+@heading 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.
+
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) @var{year} @var{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 @url{https://www.gnu.org/licenses/}.
+@end smallexample
+
+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:
+
+@smallexample
+@var{program} Copyright (C) @var{year} @var{name of author}
+This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type @samp{show c} for details.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{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
+@url{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 @url{https://www.gnu.org/licenses/why-not-lgpl.html}.
--- /dev/null
+# integration/bash --- Bash integration
+
+# Copyright (C) 2022 Akib Azmain Turja.
+
+# This file is not part of GNU Emacs.
+
+# This file 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, 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.
+
+# For a full copy of the GNU General Public License
+# see <https://www.gnu.org/licenses/>.
+
+__eat_prompt_command () {
+ # Send exit status.
+ if test -n "$__eat_current_command"
+ then
+ printf '\e]51;e;H;%i\e\\' "$__eat_exit_status"
+ fi
+ __eat_current_command=""
+ # Inform that a new prompt is going to be printed.
+ printf '\e]51;e;J\e\\'
+ # Send the current working directory, for directory tracking.
+ printf '\e]51;e;A;%s;%s\e\\' "$(printf "%s" "$HOSTNAME" | base64)" \
+ "$(printf "%s" "$PWD" | base64)"
+ # Update title.
+ # "${PWD/$HOME/'~'}" converts "/home/akib/org/" to "~/org/".
+ # The next one is substituted with '$', or '#' if we're "root".
+ printf '\e]2;%s@%s:%s%s\e\\' "$USER" "$HOSTNAME" \
+ "${PWD/$HOME/'~'}" \
+ "$(test $UID -eq 0 && echo '#' || echo '$')"
+}
+
+__eat_preexec () {
+ # Get the real command typed by the user from the history.
+ __eat_current_command="$(history 1 | sed 's/ *[0-9]* *//')"
+ # Send current command.
+ printf '\e]51;e;F;%s\e\\' \
+ "$(printf "%s" "$__eat_current_command" | base64)"
+ # Send pre-exec sequence.
+ printf '\e]51;e;G\e\\'
+ # Update title to include the command running.
+ # "${PWD/$HOME/'~'}" converts "/home/akib/foo/" to "~/foo/".
+ # The next one is substituted with '$', or '#' if we're "root".
+ printf '\e]2;%s@%s:%s%s %s\e\\' "$USER" "$HOSTNAME" \
+ "${PWD/$HOME/'~'}" \
+ "$(test $UID -eq 0 && echo '#' || echo '$')" \
+ "$__eat_current_command"
+}
+
+__eat_before_prompt_command ()
+{
+ __eat_exit_status="$?"
+ __eat_inhibit_preexec=yes
+}
+
+__eat_after_prompt_command ()
+{
+ __eat_inhibit_preexec=no
+}
+
+__eat_before_exec () {
+ if test $__eat_inhibit_preexec = no \
+ && test "$BASH_COMMAND" != __eat_before_prompt_command
+ then
+ __eat_inhibit_preexec=yes
+ __eat_preexec
+ fi
+}
+
+__eat_enable_integration ()
+{
+ __eat_integration_enabled=yes
+ __eat_current_command=""
+ __eat_exit_status=0
+ __eat_inhibit_preexec=yes
+ local __eat_prompt_start='\e]51;e;B\e\\'
+ local __eat_prompt_end='\e]51;e;C\e\\'
+ local __eat_continuation_start='\e]51;e;D\e\\'
+ local __eat_continuation_end='\e]51;e;E\e\\'
+ PS1="\[$__eat_prompt_start\]$PS1\[$__eat_prompt_end\]"
+ PS2="\[$__eat_continuation_start\]$PS2\[$__eat_continuation_end\]"
+ PROMPT_COMMAND+=(__eat_prompt_command)
+ trap '__eat_before_exec' DEBUG
+ # Wrap 'PROMPT_COMMAND' to avoid it getting trapped in 'DEBUG' trap.
+ # Fun fact: Microsoft doesn't still about know this simple trick.
+ # They ended up using something as silly and pityful as
+ # 'VAR=$PROMPT_COMMAND' to copy a Bash array in VSCode Bash
+ # integration script, which simply won't work ever, and then
+ # complain about Bash in the comments! xD
+ PROMPT_COMMAND+=(__eat_after_prompt_command)
+ PROMPT_COMMAND=(__eat_before_prompt_command "${PROMPT_COMMAND[@]}")
+ # Send the history, for native shell prompt.
+ printf '\e]51;e;I;0;bash;%s;%s\e\\' \
+ "$(printf "%s" "$HOSTNAME" | base64)" \
+ "$(printf "%s" "$HISTFILE" | base64)"
+ local REPLY
+ IFS=$';\e' read -r -s -t 10 -d "\\" -a REPLY
+ if test "${REPLY[4]}" != 0
+ then
+ printf '\e]51;e;I;1;bash;%s\e\\' \
+ "$(tail -n "${REPLY[4]}" "$HISTFILE" | base64)"
+ fi
+}
+
+_eat_msg () {
+ local msg=$'\e]51;e;M'
+ for _ in $(eval "echo {1..$#}")
+ do
+ msg="$msg;$(printf "%s" "$1" | base64)"
+ shift
+ done
+ printf "%s\e\\" "$msg"
+}
+
+# Enable.
+if test -z "$__eat_integration_enabled" && \
+ test "${TERM:0:4}" = "eat-"
+then
+ __eat_enable_integration
+else
+ true
+fi
+
+# Local Variables:
+# mode: sh
+# sh-shell: bash
+# End:
--- /dev/null
+# integration/zsh --- Zsh integration
+
+# Copyright (C) 2022, 2023 Akib Azmain Turja.
+
+# This file is not part of GNU Emacs.
+
+# This file 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, 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.
+
+# For a full copy of the GNU General Public License
+# see <https://www.gnu.org/licenses/>.
+
+__eat_precmd () {
+ __eat_exit_status="$?"
+ # Send exit status.
+ if test -n "$__eat_current_command"
+ then
+ printf '\e]51;e;H;%i\e\\' "$__eat_exit_status"
+ fi
+ __eat_current_command=""
+ # Inform that a new prompt is going to be printed.
+ printf '\e]51;e;J\e\\'
+ # Send the current working directory, for directory tracking.
+ printf '\e]51;e;A;%s;%s\e\\' "$(printf "%s" "$HOST" | base64)" \
+ "$(printf "%s" "$PWD" | base64)"
+ # Update title.
+ # "${PWD/$HOME/'~'}" converts "/home/akib/org/" to "~/org/".
+ # The next one is substituted with '%', or '#' if we're "root".
+ printf '\e]2;%s@%s:%s%s\e\\' "$USER" "$HOST" "${PWD/$HOME/~}" \
+ "$(test $UID -eq 0 && echo '#' || echo '%')"
+}
+
+__eat_preexec () {
+ __eat_current_command="$1"
+ # Send current command.
+ printf '\e]51;e;F;%s\e\\' \
+ "$(printf "%s" "$__eat_current_command" | base64)"
+ # Send pre-exec sequence.
+ printf '\e]51;e;G\e\\'
+ # Update title to include the command running.
+ # "${PWD/$HOME/~}" converts "/home/akib/foo/" to "~/foo/".
+ # The next one is substituted with '%', or '#' if we're "root".
+ printf '\e]2;%s@%s:%s%s %s\e\\' "$USER" "$HOST" "${PWD/$HOME/~}" \
+ "$(test $UID -eq 0 && echo '#' || echo '%')" \
+ "$__eat_current_command"
+}
+
+__eat_enable_integration ()
+{
+ __eat_integration_enabled=yes
+ __eat_current_command=""
+ __eat_exit_status=0
+ local __eat_prompt_start="$(printf '\e]51;e;B\e\\')"
+ local __eat_prompt_end="$(printf '\e]51;e;C\e\\')"
+ local __eat_continuation_start="$(printf '\e]51;e;D\e\\')"
+ local __eat_continuation_end="$(printf '\e]51;e;E\e\\')"
+ PS1="%{$__eat_prompt_start%}$PS1%{$__eat_prompt_end%}"
+ PS2="%{$__eat_continuation_start%}$PS2%{$__eat_continuation_end%}"
+ # TODO: What to do about RPS1 and friends?
+ autoload -Uz add-zsh-hook
+ add-zsh-hook precmd __eat_precmd
+ add-zsh-hook preexec __eat_preexec
+ # Send the history, for native shell prompt.
+ printf '\e]51;e;I;0;bash;%s;%s\e\\' \
+ "$(printf "%s" "$HOSTNAME" | base64)" \
+ "$(printf "%s" "$HISTFILE" | base64)"
+ local REPLY
+ IFS=$';\e' read -r -s -t 10 -d "\\" -A REPLY
+ if test "${REPLY[5]}" != 0
+ then
+ printf '\e]51;e;I;1;zsh;%s\e\\' \
+ "$(tail -n "${REPLY[5]}" "$HISTFILE" | base64)"
+ fi
+}
+
+_eat_msg () {
+ local msg=$'\e]51;e;M'
+ for _ in $(eval "echo {1..$#}")
+ do
+ msg="$msg;$(printf "%s" "$1" | base64)"
+ shift
+ done
+ printf "%s\e\\" "$msg"
+}
+
+# Enable.
+if test -z "$__eat_integration_enabled" && \
+ test "${TERM:0:4}" = "eat-"
+then
+ __eat_enable_integration
+else
+ true
+fi
+
+# Local Variables:
+# mode: sh
+# sh-shell: zsh
+# End:
--- /dev/null
+;;; eat.el --- Terminal initialization for Eat -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Akib Azmain Turja.
+
+;; Author: Akib Azmain Turja <akibNOSPAMdisroot.org>
+;; Created: 2022-12-04
+
+;; This file is not part of GNU Emacs.
+
+;; This file 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, 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.
+
+;; For a full copy of the GNU General Public License
+;; see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Extra support for the Eat terminal emulator.
+
+;;; Code:
+
+(require 'term/xterm)
+
+(defcustom xterm-eat-extra-capabilities
+ '(modifyOtherKeys reportBackground getSelection setSelection)
+ "List of extra capabilities supported in Eat.
+
+Each element of the list enables a feature. The elements can be:
+
+`modifyOtherKeys' More key bindings work (e.g., \"\\C-,\")
+`reportBackground' Eat reports the terminal background color.
+`getSelection' Eat yanks text from parent Emacs `kill-ring'.
+`setSelection' Eat saves killed text to parent Emacs `kill-ring'."
+ :type xterm--extra-capabilities-type
+ :group 'eat)
+
+(defun terminal-init-eat ()
+ "Terminal initialization function for Eat."
+ (let ((xterm-extra-capabilities xterm-eat-extra-capabilities))
+ (tty-run-terminal-initialization (selected-frame) "xterm")))
+
+(provide 'term/eat)
+;;; eat.el ends here