From: Andreas Gerler Date: Tue, 6 Feb 2024 08:58:01 +0000 (+0100) Subject: installed eat X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=439f05afaa951e88f818070a9ba604da34bcb01f;p=emacsconfig.git installed eat Signed-off-by: Andreas Gerler --- diff --git a/bba-shell.org b/bba-shell.org index f94364a2..9a638b49 100644 --- a/bba-shell.org +++ b/bba-shell.org @@ -78,6 +78,14 @@ A little bit of code from https://github.com/bodil/emacs.d/blob/master/bodil/bod (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] diff --git a/elpa/eat-0.9.4.signed b/elpa/eat-0.9.4.signed new file mode 100644 index 00000000..c9a1732c --- /dev/null +++ b/elpa/eat-0.9.4.signed @@ -0,0 +1,2 @@ +Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) (trust undefined) created at 2023-12-15T23:10:04+0100 using RSA +Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) (trust undefined) created at 2023-12-15T23:10:04+0100 using EDDSA \ No newline at end of file diff --git a/elpa/eat-0.9.4/.dir-locals.el b/elpa/eat-0.9.4/.dir-locals.el new file mode 100644 index 00000000..b5109671 --- /dev/null +++ b/elpa/eat-0.9.4/.dir-locals.el @@ -0,0 +1,8 @@ +;;; 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)))))) diff --git a/elpa/eat-0.9.4/.elpaignore b/elpa/eat-0.9.4/.elpaignore new file mode 100644 index 00000000..cb770cbd --- /dev/null +++ b/elpa/eat-0.9.4/.elpaignore @@ -0,0 +1,6 @@ +CONTRIBUTE +Makefile +eat-tests.el +gitlog-to-changelog +make-changelog +texinfo.tex diff --git a/elpa/eat-0.9.4/COPYING b/elpa/eat-0.9.4/COPYING new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/elpa/eat-0.9.4/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/elpa/eat-0.9.4/ChangeLog b/elpa/eat-0.9.4/ChangeLog new file mode 100644 index 00000000..8574880b --- /dev/null +++ b/elpa/eat-0.9.4/ChangeLog @@ -0,0 +1,1993 @@ +2023-12-15 Akib Azmain Turja + + 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 + + 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 + + * eat.ti (eat-mono): Remove unused capability 'Ed' + +2023-10-17 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + Fix Makefile + + * Makefile (eat.elc, check): Pass $(EMACSFLAGS) to $(EMACS). + +2023-10-07 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + Enable shell command completion by default + + * eat.el (eat-mode): Use shell mode's completion facilities. + +2023-10-04 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + * eat.el (eat-enable-alternative-display): Obsolete + +2023-10-02 Akib Azmain Turja + + 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 + + Support + + * eat.el (eat-term-input-event): Handle '' and '' + events. + * eat.el (eat-term-make-keymap): Bind '' and ''. + * eat.ti (eat-mono): Add 'kcbt' capability. + +2023-09-27 Akib Azmain Turja + + Handle output correctly in emacs mode in Eshell + + * eat.el (eat--eshell-output-filter): Inhibit read only. + +2023-09-24 Akib Azmain Turja + + Add command 'eat-send-password' + + * eat.el (eat-send-password): New command. + * eat.texi (Password Input): New chapter. + +2023-09-24 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + Fix input handling in Eshell + + * eat.el (eat--eshell-local-mode): Make input processing + variables buffer-local. + +2023-09-14 Akib Azmain Turja + + * eat.el (eat-prompt-newline): Make ring if needed + +2023-09-14 Illia Ostapyshyn + + * eat.el (eat-mode): Escape '%' character in title + +2023-09-14 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + Disable native shell prompt editing by default + + * eat.el (eat-enable-native-shell-prompt-editing): Set to nil. + +2023-09-13 Akib Azmain Turja + + 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 + + * eat.el (eat-project-other-window): New command + +2023-08-31 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + Bind 'S-' to 'eat-yank' + + * eat.el (eat--eshell-prepare-semi-char-mode-map) + (eat--prepare-semi-char-mode-map): Bind 'S-' to + 'eat-yank'. + +2023-07-06 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + Fix directory tracking in Zsh + + * integration/zsh (__eat_precmd): Use '$HOST' instead of + '$HOSTNAME'. + +2023-03-31 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + * eat.texi (Querying Before Kill): New chapter + +2023-02-07 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + 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 + to 'eat-xterm-paste'. + +2022-12-28 Akib Azmain Turja + + 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 + + * 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 + + 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 + + * README.org (Straight.el): New section + +2022-12-22 Akib Azmain Turja + + 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 + + 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 + + * eat.el (eat--t-handle-output): Fix NULL handling + +2022-12-17 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + * integration/bash: Check TERM before enabling + + * eat.el (eat-eshell-emacs-mode-map): Disable undo + +2022-12-11 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + * 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + Fix Bash integration + + * integration/bash (__eat_enable_integration): Fix moving + 'PROMPT_COMMAND' array elements. + +2022-12-04 Akib Azmain Turja + + * eat.el: Fix bright faces face definitions + +2022-12-04 Akib Azmain Turja + + 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 + + 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 + + * README.org (Quelpa): Update recipe. + + * term/eat.el: New file. + +2022-12-04 Akib Azmain Turja + + 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 + + * 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 + + Use more uniform names for tracer functions + + * eat.el: Rename 'eat--eshell-trace-...' symbols to + 'eat--trace-eshell-...'. + +2022-12-03 Akib Azmain Turja + + 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 + + Check terminal contents while testing bell + + * eat-tests.el (eat-test-character-sets): Check terminal + contents. + +2022-12-01 Akib Azmain Turja + + Refer to Info manual to setup directory tracking + + * eat.el (eat-enable-directory-tracking): Refer to Info manual. + +2022-12-01 Akib Azmain Turja + + 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 + + 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 + + * eat.el: Use loop to define color and font faces + +2022-11-30 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + Use 'vector' directly instead of backquote + + * eat.el (eat-term-make-keymap): Use 'vector' directly instead + of backquote. + +2022-11-29 Akib Azmain Turja + + * eat.el (eat-term-make-keymap): Use 'cl-flet' + +2022-11-29 Akib Azmain Turja + + 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 + + * 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 + + 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 + + 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 + + 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 + + * eat.el (eat--t-change-charset): Assert argument + +2022-11-28 Akib Azmain Turja + + 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 + + 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 + + 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 + + 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 + + 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 + + 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 + + * README.org (NonGNU ELPA Devel): New section + +2022-11-28 Akib Azmain Turja + + 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 + + * .elpaignore: New file. + +2022-11-25 Akib Azmain Turja + + 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 + + * Makefile (all): Remove "check" and "changelog." + +2022-11-24 Akib Azmain Turja + + 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 + + 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 + + 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 . diff --git a/elpa/eat-0.9.4/NEWS b/elpa/eat-0.9.4/NEWS new file mode 100644 index 00000000..125ea3a2 --- /dev/null +++ b/elpa/eat-0.9.4/NEWS @@ -0,0 +1,32 @@ +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. + + +---------------------------------------------------------------------- +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 . + diff --git a/elpa/eat-0.9.4/README-elpa b/elpa/eat-0.9.4/README-elpa new file mode 100644 index 00000000..865eab83 --- /dev/null +++ b/elpa/eat-0.9.4/README-elpa @@ -0,0 +1,245 @@ + ━━━━━━━━━━━━━━━━━━━━━━━━━ + 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] + + + +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] + +[St] + +[Kitty] + +[XTerm] + +[Linux-libre] + +[Term] + + +[Coterm] + +[Shell] + + +[Vterm] + +[Eshell] + + +[GNU Emacs] diff --git a/elpa/eat-0.9.4/README.org b/elpa/eat-0.9.4/README.org new file mode 100644 index 00000000..44dca976 --- /dev/null +++ b/elpa/eat-0.9.4/README.org @@ -0,0 +1,196 @@ +#+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]] diff --git a/elpa/eat-0.9.4/dir b/elpa/eat-0.9.4/dir new file mode 100644 index 00000000..0644aa2b --- /dev/null +++ b/elpa/eat-0.9.4/dir @@ -0,0 +1,18 @@ +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. + +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" 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. diff --git a/elpa/eat-0.9.4/eat-autoloads.el b/elpa/eat-0.9.4/eat-autoloads.el new file mode 100644 index 00000000..46ae45f2 --- /dev/null +++ b/elpa/eat-0.9.4/eat-autoloads.el @@ -0,0 +1,146 @@ +;;; 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))) + + + +;;; 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-")) + +;;; 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 diff --git a/elpa/eat-0.9.4/eat-pkg.el b/elpa/eat-0.9.4/eat-pkg.el new file mode 100644 index 00000000..3e434469 --- /dev/null +++ b/elpa/eat-0.9.4/eat-pkg.el @@ -0,0 +1,2 @@ +;; 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" . "akib@disroot.org")) :maintainer '("Akib Azmain Turja" . "akib@disroot.org") :keywords '("terminals" "processes") :url "https://codeberg.org/akib/emacs-eat") diff --git a/elpa/eat-0.9.4/eat.el b/elpa/eat-0.9.4/eat.el new file mode 100644 index 00000000..41fdee58 --- /dev/null +++ b/elpa/eat-0.9.4/eat.el @@ -0,0 +1,8294 @@ +;;; 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 +;; 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 . + +;;; 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) + + +;;;; 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. + +\\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)) + + +;;;; 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)))))))) + + +;;;; 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 "" + (let ((strs '(""))) + (dotimes (i (cdr char-size)) + (dotimes (j (car char-size)) + (when-let* ((color (aref (aref bitmap i) j))) + (push + (concat + "" 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 @. + (`((?@) nil ((,n))) + (eat--t-insert-char n)) + ;; CSI A. + ;; CSI k. + (`((,(or ?A ?k)) nil ((,n))) + (eat--t-cur-up n)) + ;; CSI B. + ;; CSI e. + (`((,(or ?B ?e)) nil ((,n))) + (eat--t-cur-down n)) + ;; CSI C. + ;; CSI a. + (`((,(or ?C ?a)) nil ((,n))) + (eat--t-cur-right n)) + ;; CSI D. + ;; CSI j. + (`((,(or ?D ?j)) nil ((,n))) + (eat--t-cur-left n)) + ;; CSI E. + (`((?E) nil ((,n))) + (eat--t-beg-of-prev-line n)) + ;; CSI F. + (`((?F) nil ((,n))) + (eat--t-beg-of-next-line n)) + ;; CSI G. + ;; CSI `. + (`((,(or ?G ?`)) nil ((,n))) + (eat--t-cur-horizontal-abs n)) + ;; CSI ; H + ;; CSI ; f + (`((,(or ?H ?f)) nil ,(and (pred listp) params)) + (eat--t-goto (caadr params) (caar params))) + ;; CSI I. + (`((?I) nil ((,n))) + (eat--t-horizontal-tab n)) + ;; CSI J. + (`((?J) nil ((,n))) + (eat--t-erase-in-disp n)) + ;; CSI K. + (`((?K) nil ((,n))) + (eat--t-erase-in-line n)) + ;; CSI L. + (`((?L) nil ((,n))) + (eat--t-insert-line n)) + ;; CSI M. + (`((?M) nil ((,n))) + (eat--t-delete-line n)) + ;; CSI P. + (`((?P) nil ((,n))) + (eat--t-delete-char n)) + ;; CSI S. + (`((?S) nil ((,n))) + (eat--t-scroll-up n)) + ;; CSI ? ; ; ... S. + (`((?S) ?? ,(or `((,_) (,operation) (,attr)) + `((,_) (,_) (,operation) (,attr)))) + (eat--t-send-graphics-attrs attr operation)) + ;; CSI T. + (`((?T) nil ((,n))) + (eat--t-scroll-down n)) + ;; CSI X. + (`((?X) nil ((,n))) + (eat--t-erase-char n)) + ;; CSI Z. + (`((?Z) nil ((,n))) + (eat--t-horizontal-backtab n)) + ;; CSI b. + (`((?b) nil ((,n))) + (eat--t-repeat-last-char n)) + ;; CSI c. + ;; CSI > c. + (`((?c) ,format ((,n))) + (eat--t-send-device-attrs n format)) + ;; CSI 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 SP q. + (`((?q ?\ ) nil ((,n))) + (eat--t-set-cursor-style n)) + ;; CSI ; 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 ; ST. + ;; OSC 2 ; ST. + ((rx string-start (or ?0 ?2) ?\; + (let title (zero-or-more anything)) + string-end) + (eat--t-set-title title)) + ;; OSC 7 ; 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 ; ST. + ((rx string-start "51;" + (let cmd (zero-or-more anything)) + string-end) + (eat--t-ui-cmd cmd)) + ;; OSC 5 2 ; ; 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- 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))) + + +;;;; 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))))) + + +;;;; 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))))) + + +;;;; 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 ; ; 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 ; 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 ; 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 ; ; ; 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 ; ; 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)))) + + +;;;;; 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)))) + + +;;;;; 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)) + + +;;;;;; 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)) + + +;;;;; 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))))) + + +;;;;; 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)) + + +;;;;; 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)) + + +;;;; 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))) + + +;;;;; 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 ; ; 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 ; ST. + ((rx string-start "e;F;" + (let cmd (zero-or-more anything)) + string-end) + (eat--set-cmd cmd)) + ;; UIC e ; I ; 0 ; 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)))) + + +;;;;; 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))))) + + +;;;; 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))) + + +;;;; 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))) + + +;;;; 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)))))) + + +;;;;; 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 "") #'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)) + + +;;;; 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))))) + + +;;;; 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 diff --git a/elpa/eat-0.9.4/eat.info b/elpa/eat-0.9.4/eat.info new file mode 100644 index 00000000..d0559306 --- /dev/null +++ b/elpa/eat-0.9.4/eat.info @@ -0,0 +1,2756 @@ +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 + + +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. + + +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. + + +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*’, ‘*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. + + +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. + + +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’. + + +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::. + + +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. + + +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-’, 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”. + + ‘’ 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 +’. + + ‘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-’ and ‘C-’. ‘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::. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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 + ‘’ 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. + + +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? + + +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. + + +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. + + +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. + + +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. + + +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. + + +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. + + +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 . +You may send the bug report by emailing to the maintainer (‘M-x +describe-package eat ’ 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.) + + +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 ‘’ 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. + + +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. + + Everyone is permitted to copy and distribute verbatim copies of this + license document, but changing it is not allowed. + +Preamble +======== + +The GNU General Public License is a free, copyleft license for software +and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program—to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers’ and authors’ protection, the GPL clearly explains +that there is no warranty for this free software. For both users’ and +authors’ sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users’ freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS +==================== + + 0. Definitions. + + “This License” refers to version 3 of the GNU General Public + License. + + “Copyright” also means copyright-like laws that apply to other + kinds of works, such as semiconductor masks. + + “The Program” refers to any copyrightable work licensed under this + License. Each licensee is addressed as “you”. “Licensees” and + “recipients” may be individuals or organizations. + + To “modify” a work means to copy from or adapt all or part of the + work in a fashion requiring copyright permission, other than the + making of an exact copy. The resulting work is called a “modified + version” of the earlier work or a work “based on” the earlier work. + + A “covered work” means either the unmodified Program or a work + based on the Program. + + To “propagate” a work means to do anything with it that, without + permission, would make you directly or secondarily liable for + infringement under applicable copyright law, except executing it on + a computer or modifying a private copy. Propagation includes + copying, distribution (with or without modification), making + available to the public, and in some countries other activities as + well. + + To “convey” a work means any kind of propagation that enables other + parties to make or receive copies. Mere interaction with a user + through a computer network, with no transfer of a copy, is not + conveying. + + An interactive user interface displays “Appropriate Legal Notices” + to the extent that it includes a convenient and prominently visible + feature that (1) displays an appropriate copyright notice, and (2) + tells the user that there is no warranty for the work (except to + the extent that warranties are provided), that licensees may convey + the work under this License, and how to view a copy of this + License. If the interface presents a list of user commands or + options, such as a menu, a prominent item in the list meets this + criterion. + + 1. Source Code. + + The “source code” for a work means the preferred form of the work + for making modifications to it. “Object code” means any non-source + form of a work. + + A “Standard Interface” means an interface that either is an + official standard defined by a recognized standards body, or, in + the case of interfaces specified for a particular programming + language, one that is widely used among developers working in that + language. + + The “System Libraries” of an executable work include anything, + other than the work as a whole, that (a) is included in the normal + form of packaging a Major Component, but which is not part of that + Major Component, and (b) serves only to enable use of the work with + that Major Component, or to implement a Standard Interface for + which an implementation is available to the public in source code + form. A “Major Component”, in this context, means a major + essential component (kernel, window system, and so on) of the + specific operating system (if any) on which the executable work + runs, or a compiler used to produce the work, or an object code + interpreter used to run it. + + The “Corresponding Source” for a work in object code form means all + the source code needed to generate, install, and (for an executable + work) run the object code and to modify the work, including scripts + to control those activities. However, it does not include the + work’s System Libraries, or general-purpose tools or generally + available free programs which are used unmodified in performing + those activities but which are not part of the work. For example, + Corresponding Source includes interface definition files associated + with source files for the work, and the source code for shared + libraries and dynamically linked subprograms that the work is + specifically designed to require, such as by intimate data + communication or control flow between those subprograms and other + parts of the work. + + The Corresponding Source need not include anything that users can + regenerate automatically from other parts of the Corresponding + Source. + + The Corresponding Source for a work in source code form is that + same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of + copyright on the Program, and are irrevocable provided the stated + conditions are met. This License explicitly affirms your unlimited + permission to run the unmodified Program. The output from running + a covered work is covered by this License only if the output, given + its content, constitutes a covered work. This License acknowledges + your rights of fair use or other equivalent, as provided by + copyright law. + + You may make, run and propagate covered works that you do not + convey, without conditions so long as your license otherwise + remains in force. You may convey covered works to others for the + sole purpose of having them make modifications exclusively for you, + or provide you with facilities for running those works, provided + that you comply with the terms of this License in conveying all + material for which you do not control copyright. Those thus making + or running the covered works for you must do so exclusively on your + behalf, under your direction and control, on terms that prohibit + them from making any copies of your copyrighted material outside + their relationship with you. + + Conveying under any other circumstances is permitted solely under + the conditions stated below. Sublicensing is not allowed; section + 10 makes it unnecessary. + + 3. Protecting Users’ Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological + measure under any applicable law fulfilling obligations under + article 11 of the WIPO copyright treaty adopted on 20 December + 1996, or similar laws prohibiting or restricting circumvention of + such measures. + + When you convey a covered work, you waive any legal power to forbid + circumvention of technological measures to the extent such + circumvention is effected by exercising rights under this License + with respect to the covered work, and you disclaim any intention to + limit operation or modification of the work as a means of + enforcing, against the work’s users, your or third parties’ legal + rights to forbid circumvention of technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program’s source code as you + receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy an appropriate copyright notice; + keep intact all notices stating that this License and any + non-permissive terms added in accord with section 7 apply to the + code; keep intact all notices of the absence of any warranty; and + give all recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, + and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to + produce it from the Program, in the form of source code under the + terms of section 4, provided that you also meet all of these + conditions: + + a. The work must carry prominent notices stating that you + modified it, and giving a relevant date. + + b. The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in + section 4 to “keep intact all notices”. + + c. You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable + section 7 additional terms, to the whole of the work, and all + its parts, regardless of how they are packaged. This License + gives no permission to license the work in any other way, but + it does not invalidate such permission if you have separately + received it. + + d. If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has + interactive interfaces that do not display Appropriate Legal + Notices, your work need not make them do so. + + A compilation of a covered work with other separate and independent + works, which are not by their nature extensions of the covered + work, and which are not combined with it such as to form a larger + program, in or on a volume of a storage or distribution medium, is + called an “aggregate” if the compilation and its resulting + copyright are not used to limit the access or legal rights of the + compilation’s users beyond what the individual works permit. + Inclusion of a covered work in an aggregate does not cause this + License to apply to the other parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms + of sections 4 and 5, provided that you also convey the + machine-readable Corresponding Source under the terms of this + License, in one of these ways: + + a. Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b. Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that + product model, to give anyone who possesses the object code + either (1) a copy of the Corresponding Source for all the + software in the product that is covered by this License, on a + durable physical medium customarily used for software + interchange, for a price no more than your reasonable cost of + physically performing this conveying of source, or (2) access + to copy the Corresponding Source from a network server at no + charge. + + c. Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, + and only if you received the object code with such an offer, + in accord with subsection 6b. + + d. Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to + the Corresponding Source in the same way through the same + place at no further charge. You need not require recipients + to copy the Corresponding Source along with the object code. + If the place to copy the object code is a network server, the + Corresponding Source may be on a different server (operated by + you or a third party) that supports equivalent copying + facilities, provided you maintain clear directions next to the + object code saying where to find the Corresponding Source. + Regardless of what server hosts the Corresponding Source, you + remain obligated to ensure that it is available for as long as + needed to satisfy these requirements. + + e. Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the + general public at no charge under subsection 6d. + + A separable portion of the object code, whose source code is + excluded from the Corresponding Source as a System Library, need + not be included in conveying the object code work. + + A “User Product” is either (1) a “consumer product”, which means + any tangible personal property which is normally used for personal, + family, or household purposes, or (2) anything designed or sold for + incorporation into a dwelling. In determining whether a product is + a consumer product, doubtful cases shall be resolved in favor of + coverage. For a particular product received by a particular user, + “normally used” refers to a typical or common use of that class of + product, regardless of the status of the particular user or of the + way in which the particular user actually uses, or expects or is + expected to use, the product. A product is a consumer product + regardless of whether the product has substantial commercial, + industrial or non-consumer uses, unless such uses represent the + only significant mode of use of the product. + + “Installation Information” for a User Product means any methods, + procedures, authorization keys, or other information required to + install and execute modified versions of a covered work in that + User Product from a modified version of its Corresponding Source. + The information must suffice to ensure that the continued + functioning of the modified object code is in no case prevented or + interfered with solely because modification has been made. + + If you convey an object code work under this section in, or with, + or specifically for use in, a User Product, and the conveying + occurs as part of a transaction in which the right of possession + and use of the User Product is transferred to the recipient in + perpetuity or for a fixed term (regardless of how the transaction + is characterized), the Corresponding Source conveyed under this + section must be accompanied by the Installation Information. But + this requirement does not apply if neither you nor any third party + retains the ability to install modified object code on the User + Product (for example, the work has been installed in ROM). + + The requirement to provide Installation Information does not + include a requirement to continue to provide support service, + warranty, or updates for a work that has been modified or installed + by the recipient, or for the User Product in which it has been + modified or installed. Access to a network may be denied when the + modification itself materially and adversely affects the operation + of the network or violates the rules and protocols for + communication across the network. + + Corresponding Source conveyed, and Installation Information + provided, in accord with this section must be in a format that is + publicly documented (and with an implementation available to the + public in source code form), and must require no special password + or key for unpacking, reading or copying. + + 7. Additional Terms. + + “Additional permissions” are terms that supplement the terms of + this License by making exceptions from one or more of its + conditions. Additional permissions that are applicable to the + entire Program shall be treated as though they were included in + this License, to the extent that they are valid under applicable + law. If additional permissions apply only to part of the Program, + that part may be used separately under those permissions, but the + entire Program remains governed by this License without regard to + the additional permissions. + + When you convey a copy of a covered work, you may at your option + remove any additional permissions from that copy, or from any part + of it. (Additional permissions may be written to require their own + removal in certain cases when you modify the work.) You may place + additional permissions on material, added by you to a covered work, + for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material + you add to a covered work, you may (if authorized by the copyright + holders of that material) supplement the terms of this License with + terms: + + a. Disclaiming warranty or limiting liability differently from + the terms of sections 15 and 16 of this License; or + + b. Requiring preservation of specified reasonable legal notices + or author attributions in that material or in the Appropriate + Legal Notices displayed by works containing it; or + + c. Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked + in reasonable ways as different from the original version; or + + d. Limiting the use for publicity purposes of names of licensors + or authors of the material; or + + e. Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f. Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified + versions of it) with contractual assumptions of liability to + the recipient, for any liability that these contractual + assumptions directly impose on those licensors and authors. + + All other non-permissive additional terms are considered “further + restrictions” within the meaning of section 10. If the Program as + you received it, or any part of it, contains a notice stating that + it is governed by this License along with a term that is a further + restriction, you may remove that term. If a license document + contains a further restriction but permits relicensing or conveying + under this License, you may add to a covered work material governed + by the terms of that license document, provided that the further + restriction does not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you + must place, in the relevant source files, a statement of the + additional terms that apply to those files, or a notice indicating + where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in + the form of a separately written license, or stated as exceptions; + the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly + provided under this License. Any attempt otherwise to propagate or + modify it is void, and will automatically terminate your rights + under this License (including any patent licenses granted under the + third paragraph of section 11). + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate + the licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, you do not qualify to receive new licenses + for the same material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or + run a copy of the Program. Ancillary propagation of a covered work + occurring solely as a consequence of using peer-to-peer + transmission to receive a copy likewise does not require + acceptance. However, nothing other than this License grants you + permission to propagate or modify any covered work. These actions + infringe copyright if you do not accept this License. Therefore, + by modifying or propagating a covered work, you indicate your + acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically + receives a license from the original licensors, to run, modify and + propagate that work, subject to this License. You are not + responsible for enforcing compliance by third parties with this + License. + + An “entity transaction” is a transaction transferring control of an + organization, or substantially all assets of one, or subdividing an + organization, or merging organizations. If propagation of a + covered work results from an entity transaction, each party to that + transaction who receives a copy of the work also receives whatever + licenses to the work the party’s predecessor in interest had or + could give under the previous paragraph, plus a right to possession + of the Corresponding Source of the work from the predecessor in + interest, if the predecessor has it or can get it with reasonable + efforts. + + You may not impose any further restrictions on the exercise of the + rights granted or affirmed under this License. For example, you + may not impose a license fee, royalty, or other charge for exercise + of rights granted under this License, and you may not initiate + litigation (including a cross-claim or counterclaim in a lawsuit) + alleging that any patent claim is infringed by making, using, + selling, offering for sale, or importing the Program or any portion + of it. + + 11. Patents. + + A “contributor” is a copyright holder who authorizes use under this + License of the Program or a work on which the Program is based. + The work thus licensed is called the contributor’s “contributor + version”. + + A contributor’s “essential patent claims” are all patent claims + owned or controlled by the contributor, whether already acquired or + hereafter acquired, that would be infringed by some manner, + permitted by this License, of making, using, or selling its + contributor version, but do not include claims that would be + infringed only as a consequence of further modification of the + contributor version. For purposes of this definition, “control” + includes the right to grant patent sublicenses in a manner + consistent with the requirements of this License. + + Each contributor grants you a non-exclusive, worldwide, + royalty-free patent license under the contributor’s essential + patent claims, to make, use, sell, offer for sale, import and + otherwise run, modify and propagate the contents of its contributor + version. + + In the following three paragraphs, a “patent license” is any + express agreement or commitment, however denominated, not to + enforce a patent (such as an express permission to practice a + patent or covenant not to sue for patent infringement). To “grant” + such a patent license to a party means to make such an agreement or + commitment not to enforce a patent against the party. + + If you convey a covered work, knowingly relying on a patent + license, and the Corresponding Source of the work is not available + for anyone to copy, free of charge and under the terms of this + License, through a publicly available network server or other + readily accessible means, then you must either (1) cause the + Corresponding Source to be so available, or (2) arrange to deprive + yourself of the benefit of the patent license for this particular + work, or (3) arrange, in a manner consistent with the requirements + of this License, to extend the patent license to downstream + recipients. “Knowingly relying” means you have actual knowledge + that, but for the patent license, your conveying the covered work + in a country, or your recipient’s use of the covered work in a + country, would infringe one or more identifiable patents in that + country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or + arrangement, you convey, or propagate by procuring conveyance of, a + covered work, and grant a patent license to some of the parties + receiving the covered work authorizing them to use, propagate, + modify or convey a specific copy of the covered work, then the + patent license you grant is automatically extended to all + recipients of the covered work and works based on it. + + A patent license is “discriminatory” if it does not include within + the scope of its coverage, prohibits the exercise of, or is + conditioned on the non-exercise of one or more of the rights that + are specifically granted under this License. You may not convey a + covered work if you are a party to an arrangement with a third + party that is in the business of distributing software, under which + you make payment to the third party based on the extent of your + activity of conveying the work, and under which the third party + grants, to any of the parties who would receive the covered work + from you, a discriminatory patent license (a) in connection with + copies of the covered work conveyed by you (or copies made from + those copies), or (b) primarily for and in connection with specific + products or compilations that contain the covered work, unless you + entered into that arrangement, or that patent license was granted, + prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting + any implied license or other defenses to infringement that may + otherwise be available to you under applicable patent law. + + 12. No Surrender of Others’ Freedom. + + If conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, they + do not excuse you from the conditions of this License. If you + cannot convey a covered work so as to satisfy simultaneously your + obligations under this License and any other pertinent obligations, + then as a consequence you may not convey it at all. For example, + if you agree to terms that obligate you to collect a royalty for + further conveying from those to whom you convey the Program, the + only way you could satisfy both those terms and this License would + be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have + permission to link or combine any covered work with a work licensed + under version 3 of the GNU Affero General Public License into a + single combined work, and to convey the resulting work. The terms + of this License will continue to apply to the part which is the + covered work, but the special requirements of the GNU Affero + General Public License, section 13, concerning interaction through + a network will apply to the combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new + versions of the GNU General Public License from time to time. Such + new versions will be similar in spirit to the present version, but + may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies that a certain numbered version of the GNU + General Public License “or any later version” applies to it, you + have the option of following the terms and conditions either of + that numbered version or of any later version published by the Free + Software Foundation. If the Program does not specify a version + number of the GNU General Public License, you may choose any + version ever published by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future + versions of the GNU General Public License can be used, that + proxy’s public statement of acceptance of a version permanently + authorizes you to choose that version for the Program. + + Later license versions may give you additional or different + permissions. However, no additional obligations are imposed on any + author or copyright holder as a result of your choosing to follow a + later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE + COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE + RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. + SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES + AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE + THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA + BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF + THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided + above cannot be given local legal effect according to their terms, + reviewing courts shall apply local law that most closely + approximates an absolute waiver of all civil liability in + connection with the Program, unless a warranty or assumption of + liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS +=========================== + +How to Apply These Terms to Your New Programs +============================================= + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least the +“copyright” line and a pointer to where the full notice is found. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) YEAR NAME OF AUTHOR + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Also add information on how to contact you by electronic and paper +mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + 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 . + + 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 . + + +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. + + + 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 + . + + 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. + + +File: docQL52HQ.info, Node: Index, Prev: GNU Free Documentation License, Up: Top + +Appendix C Index +**************** + +[index] +* 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 (“line mode”): Input Modes. (line 102) +* C-d (“line mode”): Input Modes. (line 108) +* C- (“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- (“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) +* (“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) +* (“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) + + + +Tag Table: +Node: Top721 +Node: Intro2983 +Node: Hello Terminal3829 +Node: Project-local Terminal4961 +Node: Eshell Terminal5469 +Node: Keyboard6664 +Node: Mouse7662 +Node: Input Modes8046 +Ref: Semi-char Mode8745 +Ref: Char Mode10496 +Ref: Emacs Mode11342 +Ref: Line Mode12018 +Node: Password Input14724 +Node: Shell Integration15433 +Ref: Directory tracking16175 +Ref: Shell Prompt Navigation16735 +Ref: Shell Prompt Annotation17280 +Ref: Message Passing19113 +Ref: Line Mode Integration20412 +Node: Querying Before Kill20852 +Node: Display21853 +Node: Scrollback22479 +Node: Cursor Types23418 +Node: Mouse Tracking25880 +Node: Clipboard26429 +Node: Colors27774 +Node: Fonts30502 +Node: Sixel31663 +Node: Blinking Text33105 +Node: Performance Tuning35117 +Node: Common Problems39780 +Node: Not Recognized40430 +Node: Garbled Text42205 +Node: Input Invisible43476 +Node: Not Responding44196 +Node: Signaled an Error44927 +Node: Bugs in Manual45941 +Node: Reporting Bugs46766 +Node: Tracing the Terminal49486 +Node: GNU General Public License50968 +Node: GNU Free Documentation License88787 +Node: Index114156 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/eat-0.9.4/eat.texi b/elpa/eat-0.9.4/eat.texi new file mode 100644 index 00000000..a7ca74cc --- /dev/null +++ b/elpa/eat-0.9.4/eat.texi @@ -0,0 +1,1480 @@ +\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*}, @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 diff --git a/elpa/eat-0.9.4/eat.ti b/elpa/eat-0.9.4/eat.ti new file mode 100644 index 00000000..58cb5210 --- /dev/null +++ b/elpa/eat-0.9.4/eat.ti @@ -0,0 +1,206 @@ +# 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, diff --git a/elpa/eat-0.9.4/fdl.texi b/elpa/eat-0.9.4/fdl.texi new file mode 100644 index 00000000..eaf3da0e --- /dev/null +++ b/elpa/eat-0.9.4/fdl.texi @@ -0,0 +1,505 @@ +@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: diff --git a/elpa/eat-0.9.4/gpl.texi b/elpa/eat-0.9.4/gpl.texi new file mode 100644 index 00000000..c007dc06 --- /dev/null +++ b/elpa/eat-0.9.4/gpl.texi @@ -0,0 +1,717 @@ +@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}. diff --git a/elpa/eat-0.9.4/integration/bash b/elpa/eat-0.9.4/integration/bash new file mode 100644 index 00000000..897c11d2 --- /dev/null +++ b/elpa/eat-0.9.4/integration/bash @@ -0,0 +1,134 @@ +# 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 . + +__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: diff --git a/elpa/eat-0.9.4/integration/zsh b/elpa/eat-0.9.4/integration/zsh new file mode 100644 index 00000000..6b7d7ac6 --- /dev/null +++ b/elpa/eat-0.9.4/integration/zsh @@ -0,0 +1,105 @@ +# 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 . + +__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: diff --git a/elpa/eat-0.9.4/term/eat.el b/elpa/eat-0.9.4/term/eat.el new file mode 100644 index 00000000..bb2e8e56 --- /dev/null +++ b/elpa/eat-0.9.4/term/eat.el @@ -0,0 +1,50 @@ +;;; eat.el --- Terminal initialization for Eat -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Akib Azmain Turja. + +;; Author: Akib Azmain Turja +;; 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 . + +;;; 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 diff --git a/elpa/eat-0.9.4/terminfo/65/eat-256color b/elpa/eat-0.9.4/terminfo/65/eat-256color new file mode 100644 index 00000000..9422b9d8 Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/65/eat-256color differ diff --git a/elpa/eat-0.9.4/terminfo/65/eat-color b/elpa/eat-0.9.4/terminfo/65/eat-color new file mode 100644 index 00000000..19768a7f Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/65/eat-color differ diff --git a/elpa/eat-0.9.4/terminfo/65/eat-mono b/elpa/eat-0.9.4/terminfo/65/eat-mono new file mode 100644 index 00000000..21ca9af7 Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/65/eat-mono differ diff --git a/elpa/eat-0.9.4/terminfo/65/eat-truecolor b/elpa/eat-0.9.4/terminfo/65/eat-truecolor new file mode 100644 index 00000000..d307bbb3 Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/65/eat-truecolor differ diff --git a/elpa/eat-0.9.4/terminfo/e/eat-256color b/elpa/eat-0.9.4/terminfo/e/eat-256color new file mode 100644 index 00000000..9422b9d8 Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/e/eat-256color differ diff --git a/elpa/eat-0.9.4/terminfo/e/eat-color b/elpa/eat-0.9.4/terminfo/e/eat-color new file mode 100644 index 00000000..19768a7f Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/e/eat-color differ diff --git a/elpa/eat-0.9.4/terminfo/e/eat-mono b/elpa/eat-0.9.4/terminfo/e/eat-mono new file mode 100644 index 00000000..21ca9af7 Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/e/eat-mono differ diff --git a/elpa/eat-0.9.4/terminfo/e/eat-truecolor b/elpa/eat-0.9.4/terminfo/e/eat-truecolor new file mode 100644 index 00000000..d307bbb3 Binary files /dev/null and b/elpa/eat-0.9.4/terminfo/e/eat-truecolor differ