pax_global_header00006660000000000000000000000064136110757670014527gustar00rootroot0000000000000052 comment=46bb948345f165ebffe6ff3116e36a3b8a3f219d emacs-scala-mode-1.1.0/000077500000000000000000000000001361107576700146215ustar00rootroot00000000000000emacs-scala-mode-1.1.0/.ert-runner000066400000000000000000000000041361107576700167150ustar00rootroot00000000000000-L .emacs-scala-mode-1.1.0/.gitignore000066400000000000000000000000251361107576700166060ustar00rootroot00000000000000*.elc .cask *-pkg.el emacs-scala-mode-1.1.0/Cask000066400000000000000000000013701361107576700154260ustar00rootroot00000000000000;;-*- Mode: Emacs-Lisp -*- ;;; Cask --- project definition ;; Copyright (C) 2015 Sam Halliday ;; Author: Sam Halliday ;;; Commentary: ;; ;; Cask is a package manager for emacs lisp projects, this generates ;; the *-pkg.el file and could be our test runner in the future. ;; ;; See http://cask.readthedocs.org/en/latest/guide/dsl.html for more ;; information about Cask. ;; ;; cask pkg-file ;; ;; cask update ;; cask install ;; ;; are particularly useful commands. ;; ;; To run the tests: ;; cask exec ert-runner ;; ;;; Code: (source melpa-stable) (package-file "scala-mode.el") (development (depends-on "ert-runner") (depends-on "ecukes") (depends-on "espuds") (depends-on "undercover")) ;;; Cask ends here emacs-scala-mode-1.1.0/LICENSE000066400000000000000000001045131361107576700156320ustar00rootroot00000000000000 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 . emacs-scala-mode-1.1.0/Makefile000066400000000000000000000102731361107576700162640ustar00rootroot00000000000000############################################################-*-Makefile-*-#### # Makefile for compiling the major mode of Emacs ############################################################################## ## This Makefile has been copied from the scala project. ## See the LICENSE at the bottom of this file. ############################################################################## # Configuration ROOT = . SOURCE_DIR = $(ROOT) ############################################################################## # Variables MODE_NAME = scala-mode # Emacs Lisp ELISP_COMMAND ?= emacs ELISP_OPTIONS += -batch -no-site-file -q ELISP_OPTIONS += -L $(ROOT) ELISP_FILES += $(MODE_NAME)-lib ELISP_FILES += $(MODE_NAME) ELISP_FILES += $(MODE_NAME)-syntax ELISP_FILES += $(MODE_NAME)-indent ELISP_FILES += $(MODE_NAME)-paragraph ELISP_FILES += $(MODE_NAME)-prettify-symbols ELISP_FILES += $(MODE_NAME)-imenu ELISP_FILES += $(MODE_NAME)-fontlock ELISP_FILES += $(MODE_NAME)-map ELISP_SOURCES += $(ELISP_FILES:%=$(SOURCE_DIR)/%.el) PKG_FILE += $(SOURCE_DIR)/$(MODE_NAME)-pkg.el ############################################################################## RM ?= rm -f RMDIR ?= rmdir TOUCH ?= touch # Strip the version out of the pkg file VERSION := $(shell ${ELISP_COMMAND} $(ELISP_OPTIONS) --eval '(princ (format "%s\n" (nth 2 (read (find-file "$(PKG_FILE)")))))') MODE_NAME_VERSION = $(MODE_NAME)-$(VERSION) ############################################################################## # Commands all: .latest-build clean: $(RM) *.elc .latest-* autoloads.el $(MODE_NAME_VERSION).tar [ ! -d $(MODE_NAME_VERSION) ] || $(RM) $(MODE_NAME_VERSION)/* [ ! -d $(MODE_NAME_VERSION) ] || $(RMDIR) $(MODE_NAME_VERSION) .PHONY: all .PHONY: clean ############################################################################## # Rules .latest-build: $(ELISP_SOURCES) $(ELISP_COMMAND) $(ELISP_OPTIONS) -f batch-byte-compile $(ELISP_SOURCES) @$(TOUCH) $@ ############################################################################## autoloads: $(ELISP_SOURCES) $(ELISP_COMMAND) $(ELISP_OPTIONS) --eval "(setq make-backup-files nil)" --eval "(setq generated-autoload-file (expand-file-name \"autoloads.el\"))" -f batch-update-autoloads `pwd` package: mkdir -p $(MODE_NAME_VERSION) cp $(ELISP_SOURCES) $(PKG_FILE) $(MODE_NAME_VERSION) tar cf $(MODE_NAME_VERSION).tar $(MODE_NAME_VERSION) ## SCALA LICENSE ## ## Copyright (c) 2002-2011 EPFL, Lausanne, unless otherwise specified. ## All rights reserved. ## ## This software was developed by the Programming Methods Laboratory of the ## Swiss Federal Institute of Technology (EPFL), Lausanne, Switzerland. ## ## Permission to use, copy, modify, and distribute this software in source ## or binary form for any purpose with or without fee is hereby granted, ## provided that the following conditions are met: ## ## 1. Redistributions of source code must retain the above copyright ## notice, this list of conditions and the following disclaimer. ## ## 2. Redistributions in binary form must reproduce the above copyright ## notice, this list of conditions and the following disclaimer in the ## documentation and/or other materials provided with the distribution. ## ## 3. Neither the name of the EPFL nor the names of its contributors ## may be used to endorse or promote products derived from this ## software without specific prior written permission. ## ## ## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ## ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. emacs-scala-mode-1.1.0/README.md000066400000000000000000000220051361107576700160770ustar00rootroot00000000000000# emacs-scala-mode The mode intends to provide basic emacs support for the Scala language, including: - local indenting of code, comments and multi-line strings - motion commands - highlighting See also (emacs-sbt-mode)[https://github.com/hvesalai/emacs-sbt-mode]. ## Installation The preferred mechanism is via MELPA and `use-package` as per our [Learning Emacs](/editors/emacs/learning) guide: ```elisp (use-package scala-mode :interpreter ("scala" . scala-mode)) ``` ## Multi-line comments The start of a multi-line comment is indented to the same level with code. By default, if a multi-line comment begins with `/*` it is considered to be a Scaladoc comment. Scaladoc comments are indented according to the Scaladoc style guide. ```scala /** This is a Scaladoc comment. * 2nd line. */ ``` Alternatively, if the configurable variable *scala-indent:use-javadoc-style* is set to `t`, multi-line comments beginning with `/**` will be indented according to the Javadoc style, wherein all following lines are indented under the first asterisk. ```scala /** * This is a Javadoc-style comment. * 2nd line. */ ``` All other multi-line comments are indented under the first asterisk. ``` /** * Supercalifragilistic- * expialidocious! */ /* A comment */ ``` Typing an asterisk in multi-line comment region, at the start of a line, will trigger indent. Furthermore, if the configurable variable `scala-indent:add-space-for-scaladoc-asterisk` is `t` (default) and the asterisk was the last character on the line, a space will be inserted after it. If you type a forward slash after the automatically inserted space, the space is deleted again so that you can end the comment without deleting the space manually. ## Filling (i.e. word wrap) Paragraph `filling` is supported for comments and multi-line strings. Auto-fill is not supported yet. To re-fill a paragraph, use the `fill-paragraph` command ( `M-q` ). As always, the column at which to wrap is controlled by the `fill-column` variable, which you set it with the `set-fill-column` command. To set the default, you use the `customize-variable` command or a mode-hook. ## Motion Emacs commands `forward-sexp` and `backward-sexp` ( `M-C-f`, `M-C-b` ) motion commands will move over reserved words, literals, ids and lists. Text paragraph motion (i.e. `forward-paragraph`, `backward-paragraph`) works inside comments and multi-line strings, and it respect Scaladoc's wiki-style markup. `scala-syntax:beginning-of-definition` and `scala-syntax:end-of-definition` move the cursor forward and backward over class, trait, object, def, val, var, and type definitions. These functions are assigned to the buffer local variables `beginning-of-defun-function` and `end-of-defun-function` which makes it so that the `beginning-of-defun` and `end-of-defun` functions behave in a way that is appropriate to scala. These functions are not currently able to support some of the more advanced scala definition types. ## Highlighting The highlighting of variable definitions, such as ```var test = "some mutable variable"``` now result in the variable name ("test" above) to be highlighted using the variable scala-font-lock:var-face. Per default, the value of scala-font-lock:var-face is 'font-lock-warning-face. You can always change the highlighting of vars by changing scala-font-lock:var-face through the Emacs face customization (use `M-x` *customize-face*). Very complex scala files may need the following in your emacs init (.emacs, etc): ```lisp ;; For complex scala files (setq max-lisp-eval-depth 50000) (setq max-specpdl-size 5000) ``` ## imenu scala-mode supports imenu, a library for accessing locations in documents that is included in emacs 24. The custom variable `scala-imenu:should-flatten-index` controls whether or not the imenu index will be hierarchical or completely flat. The current iMenu implementation only goes one level deep i.e. nested classes are not traversed. scala-mode's imenu support depends heavily on the `scala-syntax:end-of-definition` and `scala-syntax:beginning-of-definition` functions, and as such, it shares their limitations. ## Joining lines (delete indentation) and removing horizontal whitespace Scala-mode defines its own `scala-indent:join-line` and `scala-indent:fixup-whitespace` functions. Unlike the normal `join-line` (aka `delete-indentation`), `scala-indent:join-line` detects the comment fill-prefix and removes it. The `scala-indent:fixup-whitespace` first removes all horizontal whitespace, then adds one space the context requires none to be present (before semicolon, around dot, after `(` or `[`, before `)` or `]`, etc). ## Indenting **Where four developers meet, there are four opinions on how code should be indented**. `scala-mode` supports 2^4 different ways of applying local heuristics to indentation. Note that when using `sbt-scalariform`, your local indentation rules will be overwritten. ### Run-on lines Provided by `scala-indent:default-run-on-strategy` The indenting engine has three modes for handling run-on lines. The `reluctant` (default) mode is geared toward a general style of coding and the `eager` for strictly functional style. A third mode called `operators` is between the two. The difference between the modes is how they treat run-on lines. For example, the `eager` mode will indent `map` in the following code ```scala val x = List(1, 2, 3) map(x => x + 1) ``` The `operators` and `eager` modes will indent the second row in the following code, as the first line ends with an operator character. ```scala val x = 20 + 21 ``` The `reluctant` mode (default) will not indent the line in either case. However, all three modes will indent the second line in these examples as it is clear that the first line cannot terminate a statement. ```scala val x = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9). map (x => x + 1) // last token of previous line cannot terminate a statement val y = (List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) map (x => x + 1)) // inside 'newlines disabled' region ``` You can use empty lines in the `eager` mode to stop it from indenting a line. For example ```scala val x = foo("bar") ("zot", "kala") // indented as curry val y = foo("bar") ("zot", "kala") // a tuple ``` However, in all three modes pressing the `tab` key repeatedly on a line will toggle between the modes. ### Value expressions Provided by `scala-indent:indent-value-expression` When this variable is set to *nil* (default), body of a value expressions will be indented in the traditional way. ```scala val x = try { some() } catch { case e => other } finally { clean-up() } ``` However, when the variable is set to `t`, the body will be indented one extra step to make the `val`, `var` or `def` stand out. For example: ```scala val x = try { some() } catch { case e => other } finally { clean-up() } ``` ### Parameter lists Provided by `scala-indent:align-parameters` When this variable is set to `nil` (default), parameters and run-on lines in parameter lists will not align under or according to the first parameter. ```scala val y = List( "Alpha", "Bravo", "Charlie" ) val x = equals(List(1,2,3) map (x => x + 1)) ``` When the variable is set to `t`, the same will be indented as: ```scala val y = List( "Alpha", "Bravo", "Charlie" ) val x = equals(List(1,2,3) map (x => x + 1)) ``` ### Expression forms: if, for, try Provided by `scala-indent:align-forms` When this variable is set to `nil` (default), `if`, `for` and `try` forms are not aligned specially. ```scala val x = if (kala) foo else if (koira) bar else zot val x = try "1".toInt catch { case e => 0} finally { println("hello") } val xs = for (i <- 1 to 10) yield i ``` When the variable is set to `t`, the same will be indented as: ```scala val x = if (kala) foo else if (koira) bar else zot val x = try "1".toInt catch { case e => 0} finally { println("hello") } val xs = for (i <- 1 to 10) yield i ``` ## Prettify-Symbols Scala-mode has a preconfigured list of prettify-symbols rules. The `prettify-symbols-mode` minor-mode (included with emacs from version 24.4 onwards) displays text in your buffer as (usually) unicode symbols that express the same thing to improve readability. A good example would be displaying the boolean operators as their unicode equivalents. To enable the feature just add these lines to the `scala-mode-hook`: ```elisp (setq prettify-symbols-alist scala-prettify-symbols-alist) (prettify-symbols-mode) ``` Also feel free to customise the prettify rules by adding or removing from the `scala-prettify-symbols-alist` alist. Libre fonts that seems to work well with this feature are: - [Source Code Pro](https://github.com/adobe-fonts/source-code-pro) - [Hack](https://github.com/chrissimpkins/Hack) emacs-scala-mode-1.1.0/scala-mode-fontlock.el000066400000000000000000000520321361107576700207670ustar00rootroot00000000000000;;; scala-mode-fontlock.el - Major mode for editing scala, font-lock ;;; Copyright (c) 2012 Heikki Vesalainen ;;; For information on the License, see the LICENSE file (require 'scala-mode-syntax) (defcustom scala-font-lock:constant-list '() "A list of strigs that should be fontified in constant face. This customization property takes effect only after the scala-mode has been reloaded." :type '(repeat string) :group 'scala) (defun scala-font-lock:create-user-constant-re () (regexp-opt scala-font-lock:constant-list 'words)) (defun scala-font-lock:mark-reserved-symbols (limit) (when (re-search-forward scala-syntax:reserved-symbols-re limit t) (goto-char (match-end 2)))) ;; step back to the match (re matches futher) (defun scala-font-lock:mark-underscore (limit) (when (re-search-forward scala-syntax:reserved-symbol-underscore-re limit t) (goto-char (match-end 2)))) ;; step back to the match (re matches futher) ;(defun scala-font-lock:extend-region-function () (defun scala-font-lock:limit-pattern2 (&optional start) (save-excursion (when start (goto-char start)) (scala-syntax:skip-forward-ignorable) (ignore-errors (while (and (not (or (eobp) (looking-at scala-syntax:other-keywords-unsafe-re) (scala-syntax:looking-at-reserved-symbol nil))) (scala-syntax:looking-at-simplePattern-beginning)) ; (message "- now at %d" (point)) (if (= (char-after) ?\() (forward-list) ;; else (goto-char (match-end 0)) (scala-syntax:skip-forward-ignorable) ; (message "+ now at %d" (point)) (cond ((looking-at "(") (forward-list)) ((looking-at "@") (goto-char (match-end 0))) ((or (scala-syntax:looking-at-reserved-symbol nil) (looking-at scala-syntax:other-keywords-unsafe-re)) ; (messssage "saw reserved symbol or keyword") nil) ((looking-at scala-syntax:id-re) ; (message "saw id-re %d" (match-beginning 0)) (goto-char (match-end 0))) ; (t ; (message "nothing special here %s" (point))) )) (scala-syntax:skip-forward-ignorable))) ; (message "limit at %s" (point)) (point))) (defun scala-font-lock:limit-pattern2-list (&optional start) (let ((limit (scala-font-lock:limit-pattern2 start))) (while (= (char-after limit) ?,) (setq limit (scala-font-lock:limit-pattern2 (1+ limit)))) ; (message "list limit at %s" limit) limit)) (defun scala-font-lock:mark-pattern1-part (&optional limit pattern-p) "Parses a part of val, var and case pattern (or id). Always parses a variable or constant name first and then type, leaving the pointer at the next variablename, constant name, list or Pattern3, if any, and setting up match data 1 (variable), 2 (constant) and 3 (type) accordingly. If there is no variable name before the first type, then the match data for the variable name is nil. Returns t if something was matched or nil if nothing was found. If pattern-p is defined, then only varid is matched as variable and everything else is constant. Does not continue past limit. " ; (message "will stop at %d" limit) (cond ;; quit if we are past limit ((or (and limit (>= (point) limit)) (eobp)) ; (message "at limit %s" (point)) nil) ;; Type pattern, just skip the whole thing. It will end at ',' or ')'. ;; Note: forms starting with ':' are handled by a completely separete ;; font-lock matcher. ((scala-syntax:looking-at-reserved-symbol ":") ; (message ":") (while (not (or (eobp) (scala-syntax:looking-at "[,);]") (scala-syntax:looking-at-reserved-symbol "|") (scala-syntax:looking-at-reserved-symbol scala-syntax:double-arrow-unsafe-re) (scala-syntax:looking-at-empty-line-p))) (scala-syntax:forward-sexp) (scala-syntax:skip-forward-ignorable)) (set-match-data nil) t) ;; Binding part cannot start with reserved symbols. If they ;; are seen, we must quit. ((scala-syntax:looking-at-reserved-symbol nil) ; (message "symbol") nil) ((scala-syntax:looking-at-stableIdOrPath) ; (message "stableId") (let ((beg (match-beginning 0)) (end (match-end 0)) (varid (scala-syntax:looking-at-varid-p))) (goto-char end) (let ((new-match-data (cond ((= (char-after end) ?\() ;; matched type ; (message "it's a type") `(,beg ,end nil nil nil nil ,beg ,end)) ((progn (scala-syntax:backward-sexp) (= (char-before) ?.)) ;; matched constant `(,beg ,end nil nil ,(point) ,end nil nil)) ((or varid (not pattern-p)) ;; matched variable name or we can't be sure `(,beg ,end ,beg ,end nil nil nil nil)) (t ;; matched constant `(,beg ,end nil nil ,beg ,end nil nil))))) (goto-char end) (scala-syntax:skip-forward-ignorable) (cond ((and (not (or (scala-syntax:looking-at-reserved-symbol nil) (scala-syntax:looking-at-reserved-symbol "|"))) (scala-syntax:looking-at-stableIdOrPath)) (setq new-match-data (append (butlast new-match-data 2) `(,(match-beginning 0) ,(match-end 0)))) (goto-char (match-end 0)) (scala-syntax:skip-forward-ignorable)) ((= (char-after) ?@) (forward-char) (scala-syntax:skip-forward-ignorable))) (set-match-data new-match-data))) t) ;; Pattern3 can be a literal. Just skip them. ((looking-at scala-syntax:literal-re) ; (message "literal") (goto-char (match-end 0)) (scala-syntax:skip-forward-ignorable) (set-match-data nil) t) ;; Start of a patterns list or alternatives. Skip if alternatives or ;; else leave point at start of first element. ((= (char-after) ?\() ; (message "(") (let ((alternatives-p (save-excursion (forward-char) (ignore-errors ;; forward-sexp will terminate the loop with error ;; if '|' is not found before end of list ')' (while (not (or (eobp) (= (char-before) ?|) (scala-syntax:looking-at-empty-line-p))) (scala-syntax:forward-sexp)) t)))) (if alternatives-p (forward-list) (forward-char))) (scala-syntax:skip-forward-ignorable) (set-match-data nil) t) ;; continuation or end of list, just skip and position at the ;; next element ((or (= (char-after) ?,) (= (char-after) ?\))) ; (message ", or )") (forward-char) (scala-syntax:skip-forward-ignorable) (set-match-data nil) t) ;; none of the above, just stop (t ; (message "Cannot continue Pattern1 at %d" (point)) nil) )) (defun scala-font-lock:limit-pattern (&optional start) (save-excursion (goto-char (scala-font-lock:limit-pattern2 start)) ; (message "now at %d" (point)) (when (scala-syntax:looking-at-reserved-symbol ":") (while (not (or (eobp) (scala-syntax:looking-at-reserved-symbol "|") (scala-syntax:looking-at-reserved-symbol scala-syntax:double-arrow-unsafe-re) (scala-syntax:looking-at-empty-line-p))) (scala-syntax:forward-sexp) (scala-syntax:skip-forward-ignorable))) (if (or (/= (char-after) ?|) (scala-syntax:looking-at-reserved-symbol scala-syntax:double-arrow-unsafe-re)) (point) (forward-char) (scala-font-lock:limit-pattern)))) (defun scala-font-lock:mark-pattern-part (&optional limit) (when (scala-syntax:looking-at-reserved-symbol "|") ; (message "skipping |") (forward-char) (scala-syntax:skip-forward-ignorable)) (scala-font-lock:mark-pattern1-part limit t)) (defun scala-font-lock:limit-type (&optional start) start) (defun scala-font-lock:limit-simpleType (&optional start) (when start (goto-char start)) (scala-syntax:skip-forward-ignorable) (setq start (point)) (if (= (char-after) ?\() (ignore-errors (forward-list)) (scala-font-lock:mark-simpleType)) (when (and (not (eobp)) (= (char-after) ?#)) (scala-font-lock:mark-simpleType)) (when (and (not (eobp)) (= (char-after) ?\[)) (ignore-errors (forward-list)) (scala-syntax:skip-forward-ignorable)) (let ((limit (point))) (goto-char start) ; (message "simpeType limit at %d" limit) limit)) (defun scala-font-lock:mark-simpleType (&optional limit) ; (message "looking for simpleType at %d" (point)) (cond ;; stop at limit ((and limit (>= (point) limit)) nil) ;; just dive into lists ((> (skip-chars-forward "[(,)]") 0) ; (message "skipping list-marks") (scala-syntax:skip-forward-ignorable) (set-match-data nil) t) ;; jump over blocks ((= (char-after) ?\{) (ignore-errors (forward-list) (set-match-data nil) t)) ;; ignore arrows and reserved words and symbols ((or (scala-syntax:looking-at-reserved-symbol scala-syntax:double-arrow-unsafe-re) (scala-syntax:looking-at-reserved-symbol "<[:%]\\|>?:") (looking-at "\\")) ; (message "skipping reserved") (goto-char (match-end 0)) (scala-syntax:skip-forward-ignorable) (set-match-data nil) t) ;; color id after '#' ((= (char-after) ?#) ; (message "at #") (forward-char) (if (and (not (or (looking-at scala-syntax:keywords-unsafe-re) (scala-syntax:looking-at-reserved-symbol nil))) (looking-at scala-syntax:id-re)) (goto-char (match-end 0)) nil)) ;; color paths (including stableid) ((scala-syntax:looking-at-stableIdOrPath t) ; (message "at path") (let ((end (match-end 0))) (goto-char end) (while (scala-syntax:looking-back-token "this\\|type") (goto-char (match-beginning 0)) (skip-chars-backward ".")) (unless (scala-syntax:looking-back-token scala-syntax:id-re) (set-match-data nil)) (goto-char end)) (scala-syntax:skip-forward-ignorable) t) (t ; (message "Cannot continue simpleType at %d" (point)) nil))) (defun scala-font-lock:mark-string-escapes (limit) (when (re-search-forward scala-syntax:string-escape-re limit t) (goto-char (match-end 0)) (or (eq (nth 3 (save-excursion (syntax-ppss (match-beginning 0)))) ?\") (scala-font-lock:mark-string-escapes limit)))) (defun scala-font-lock:mark-numberLiteral (re limit) (when (re-search-forward re limit t) (if (string-match-p scala-syntax:number-safe-start-re ;; get char-before match or a magic ',', which is safe (string (or (char-before (match-beginning 0)) ?,))) t (scala-font-lock:mark-numberLiteral re limit)))) (defun scala-font-lock:mark-floatingPointLiteral (limit) (scala-font-lock:mark-numberLiteral scala-syntax:floatingPointLiteral-re limit)) (defun scala-font-lock:mark-integerLiteral (limit) (scala-font-lock:mark-numberLiteral scala-syntax:integerLiteral-re limit)) (defun scala-font-lock:keywords () ;; chars, string, comments are handled acording to syntax and ;; syntax propertize `(;; keywords (,scala-syntax:override-re 2 scala-font-lock:override-face) (,scala-syntax:abstract-re 2 scala-font-lock:abstract-face) (,scala-syntax:final-re 2 scala-font-lock:final-face) (,scala-syntax:sealed-re 2 scala-font-lock:sealed-face) (,scala-syntax:implicit-re 2 scala-font-lock:implicit-face) (,scala-syntax:lazy-re 2 scala-font-lock:lazy-face) (,scala-syntax:private-re 2 scala-font-lock:private-face) (,scala-syntax:protected-re 2 scala-font-lock:protected-face) (,scala-syntax:other-keywords-re 2 font-lock-keyword-face) (,scala-syntax:value-keywords-re 2 font-lock-constant-face) (,scala-syntax:path-keywords-re 2 font-lock-keyword-face) ;; User defined constants (,(scala-font-lock:create-user-constant-re) 0 font-lock-constant-face) ;; Annotations (, (rx (and "@" (in "a-zA-Z_.") (0+ (in "a-zA-Z0-9_.")))) . font-lock-preprocessor-face) ;; reserved symbols (scala-font-lock:mark-reserved-symbols 2 font-lock-keyword-face) ;; 'Symbols (,scala-syntax:symbolLiteral-re 1 font-lock-string-face) ;; underscore (scala-font-lock:mark-underscore 2 font-lock-keyword-face) ;; escapes inside strings (scala-font-lock:mark-string-escapes (0 font-lock-constant-face prepend nil)) ;; object (,(concat "\\?@\\^|~")) line-start) (group ":") (0+ space) (group (in "a-zA-Z_") (0+ (in "a-zA-Z0-9_")) (\? (and "_" (1+ (in "!#%&*+-/:<=>?@\\^|~")))))) (1 font-lock-keyword-face) (2 font-lock-type-face)) ;; type ascription (: followed by punctuation type name) (,(rx (or (not (in "!#%&*+-/:<=>?@\\^|~")) line-start) (group ":") (1+ space) (group (1+ (in "-!#%&*+/:<=>?@\\^|~")))) (1 font-lock-keyword-face) (2 font-lock-type-face)) ;; extends followed by type (,(rx symbol-start (group "extends") (1+ space) (group (or (and (in "a-zA-Z_") (0+ (in "a-zA-Z0-9_")) (\? (and "_" (1+ (in "!#%&*+-/:<=>?@\\^|~"))))) (1+ (in "!#%&*+-/:<=>?@\\^|~"))))) (1 font-lock-keyword-face) (2 font-lock-type-face)) ;; with followed by type (,(rx symbol-start (group "with") (1+ space) (group (or (and (in "a-zA-Z_") (0+ (in "a-zA-Z0-9_")) (\? (and "_" (1+ (in "!#%&*+-/:<=>?@\\^|~"))))) (1+ (in "!#%&*+-/:<=>?@\\^|~"))))) (1 font-lock-keyword-face) (2 font-lock-type-face)) ;; new followed by type (,(rx symbol-start (group "new") (1+ space) (group (or (and (in "a-zA-Z_") (0+ (in "a-zA-Z0-9_")) (\? (and "_" (1+ (in "!#%&*+-/:<=>?@\\^|~"))))) (1+ (in "!#%&*+-/:<=>?@\\^|~"))))) (1 font-lock-keyword-face) (2 font-lock-type-face)) ;; uppercase means a type or object (,(rx symbol-start (and (in "A-Z") (0+ (in "a-zA-Z0-9_")) (\? (and "_" (1+ (in "!#%&*+-/:<=>?@\\^|~")))))) . font-lock-constant-face) ;; . font-lock-type-face) ; uncomment this to go back to highlighting objects as types ;; uppercase (,(rx symbol-start (group (and (in "A-Z") (0+ (in "a-zA-Z0-9_")) (\? (and "_" (1+ (in "!#%&*+-/:<=>?@\\^|~"))))))) . font-lock-constant-face) ;; package name (,(rx symbol-start (group "package") (1+ space) (group (and (in "a-zA-Z_.") (0+ (in "a-zA-Z0-9_."))))) (1 font-lock-keyword-face) (2 font-lock-string-face)) ;; number literals (have to be here so that other rules take precedence) (scala-font-lock:mark-floatingPointLiteral . font-lock-constant-face) (scala-font-lock:mark-integerLiteral . font-lock-constant-face) (scala-syntax:interpolation-matcher 0 font-lock-variable-name-face t) )) (defun scala-font-lock:syntactic-face-function (state) "Return correct face for string or comment" (if (and (integerp (nth 4 state)) (save-excursion (goto-char (nth 8 state)) (looking-at "/\\*\\*\\($\\|[^*]\\)"))) ;; scaladoc (starts with /** only) font-lock-doc-face (if (nth 3 state) font-lock-string-face font-lock-comment-face))) (defface scala-font-lock:var-face '((t (:inherit font-lock-warning-face))) "Font Lock mode face used to highlight scala variable names." :group 'scala) (defvar scala-font-lock:var-face 'scala-font-lock:var-face "Face for scala variable names.") (defface scala-font-lock:private-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the private keyword." :group 'scala) (defvar scala-font-lock:private-face 'scala-font-lock:private-face "Face for the scala private keyword.") (defface scala-font-lock:protected-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the protected keyword." :group 'scala) (defvar scala-font-lock:protected-face 'scala-font-lock:protected-face "Face for the scala protected keyword.") (defface scala-font-lock:override-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the override keyword." :group 'scala) (defvar scala-font-lock:override-face 'scala-font-lock:override-face "Face for the scala override keyword.") (defface scala-font-lock:sealed-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the sealed keyword." :group 'scala) (defvar scala-font-lock:sealed-face 'scala-font-lock:sealed-face "Face for the scala sealed keyword.") (defface scala-font-lock:abstract-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the abstract keyword." :group 'scala) (defvar scala-font-lock:abstract-face 'scala-font-lock:abstract-face "Face for the scala abstract keyword.") (defface scala-font-lock:final-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the final keyword." :group 'scala) (defvar scala-font-lock:final-face 'scala-font-lock:final-face "Face for the scala final keyword.") (defface scala-font-lock:implicit-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the implicit keyword." :group 'scala) (defvar scala-font-lock:implicit-face 'scala-font-lock:implicit-face "Face for the scala implicit keyword.") (defface scala-font-lock:lazy-face '((t (:inherit font-lock-builtin-face))) "Font Lock mode face used for the lazy keyword." :group 'scala) (defvar scala-font-lock:lazy-face 'scala-font-lock:lazy-face "Face for the scala lazy keyword.") (defface scala-font-lock:var-keyword-face '((t (:inherit font-lock-keyword-face))) "Font Lock mode face used for the var keyword." :group 'scala) (defvar scala-font-lock:var-keyword-face 'scala-font-lock:var-keyword-face "Face for the scala var keyword.") (provide 'scala-mode-fontlock) emacs-scala-mode-1.1.0/scala-mode-imenu.el000066400000000000000000000117251361107576700202710ustar00rootroot00000000000000;;; scala-mode-imenu.el - Major mode for editing scala ;;; Copyright (c) 2014 Heikki Vesalainen ;;; For information on the License, see the LICENSE file ;;; Code: (require 'scala-mode-syntax) ;; Make lambdas proper clousures (only in this file) (make-local-variable 'lexical-binding) (setq lexical-binding t) (defcustom scala-imenu:should-flatten-index t "Controls whether or not the imenu index is flattened or hierarchical." :type 'boolean :safe #'booleanp :group 'scala) (defcustom scala-imenu:build-imenu-candidate 'scala-imenu:default-build-imenu-candidate "Controls whether or not the imenu index has definition type information." :type 'function :group 'scala) (defcustom scala-imenu:cleanup-hooks nil "Functions that will be run after the construction of each imenu" :type 'hook :group 'scala) (defun scala-imenu:flatten-list (incoming-list &optional predicate) (when (not predicate) (setq predicate 'listp)) (cl-mapcan (lambda (x) (if (funcall predicate x) (scala-imenu:flatten-list x predicate) (list x))) incoming-list)) (defun scala-imenu:flatten-imenu-index (index) (cl-mapcan (lambda (x) (if (listp (cdr x)) (scala-imenu:flatten-imenu-index (cdr x)) (list x))) index)) (defun scala-imenu:create-imenu-index () (let ((imenu-index (cl-mapcar 'scala-imenu:build-imenu-candidates (scala-imenu:create-index)))) (dolist (cleanup-hook scala-imenu:cleanup-hooks) (funcall cleanup-hook)) (if scala-imenu:should-flatten-index (scala-imenu:flatten-imenu-index imenu-index) imenu-index))) (defun scala-imenu:build-imenu-candidates (member-info &optional parents) (if (listp (car member-info)) (let* ((current-member-info (car member-info)) (child-member-infos (cdr member-info)) (current-member-result (scala-imenu:destructure-for-build-imenu-candidate current-member-info parents)) (current-member-name (car current-member-result))) (if child-member-infos (let ((current-member-members (scala-imenu:build-child-members (append parents `(,current-member-info)) (cdr member-info)))) `(,current-member-name . ,(cons current-member-result current-member-members))) current-member-result)) (scala-imenu:destructure-for-build-imenu-candidate member-info parents))) (defun scala-imenu:build-child-members (parents child-members) (cl-mapcar (lambda (child) (scala-imenu:build-imenu-candidates child parents)) child-members)) (defun scala-imenu:destructure-for-build-imenu-candidate (member-info parents) (cl-destructuring-bind (member-name definition-type marker) member-info (funcall scala-imenu:build-imenu-candidate member-name definition-type marker parents))) (defun scala-imenu:default-build-imenu-candidate (member-name definition-type marker parents) (let* ((all-names (append (cl-mapcar (lambda (parent) (car parent)) parents) `(,member-name))) (member-string (mapconcat 'identity all-names "."))) `(,(format "(%s)%s" definition-type member-string) . ,marker))) (defun scala-imenu:create-index () (let ((class nil) (index nil)) (goto-char (point-max)) (while (setq class (scala-imenu:parse-nested-from-end)) (setq index (cons class index))) index)) (defun scala-imenu:parse-nested-from-end () (let ((last-point (point)) (class-name nil) (definition-type nil)) (scala-syntax:beginning-of-definition) ;; We're done if scala-syntax:beginning-of-definition has no effect. (if (eq (point) last-point) nil (progn (looking-at scala-syntax:all-definition-re) (setq class-name (match-string-no-properties 2)) (setq definition-type (match-string-no-properties 1))) `(,`(,class-name ,definition-type ,(point-marker)) . ,(scala-imenu:nested-members))))) (defun scala-imenu:parse-nested-from-beginning () (scala-syntax:end-of-definition) (scala-imenu:parse-nested-from-end)) (defun scala-imenu:nested-members () (let ((start-point (point))) (save-excursion (scala-syntax:end-of-definition) ;; This gets us inside of the class definition ;; It seems like there should be a better way ;; to do this. (backward-char) (reverse (scala-imenu:get-nested-members start-point))))) (defvar scala-imenu:nested-definition-types '("class" "object" "trait")) (defun scala-imenu:get-nested-members (parent-start-point) (scala-syntax:beginning-of-definition) (if (< parent-start-point (point)) (cons (scala-imenu:get-member-info-at-point) (scala-imenu:get-nested-members parent-start-point)) nil)) (defun scala-imenu:get-member-info-at-point () (looking-at scala-syntax:all-definition-re) (let* ((member-name (match-string-no-properties 2)) (definition-type (match-string-no-properties 1))) (if (member definition-type scala-imenu:nested-definition-types) (save-excursion (scala-imenu:parse-nested-from-beginning)) `(,member-name ,definition-type ,(point-marker))))) (provide 'scala-mode-imenu) ;;; scala-mode-imenu.el ends here emacs-scala-mode-1.1.0/scala-mode-indent.el000066400000000000000000001120001361107576700204210ustar00rootroot00000000000000;;; scala-mode.el - Major mode for editing scala, indenting ;;; Copyright (c) 2012 Heikki Vesalainen ;;; For information on the License, see the LICENSE file (require 'scala-mode-syntax) (require 'scala-mode-lib) (eval-when-compile (defvar scala-indent:effective-run-on-strategy) (defvar scala-indent:previous-indent-pos)) (defcustom scala-indent:step 2 "The number of spaces an indentation step should be. The actual indentation will be one or two steps depending on context." :type 'integer :safe #'integerp :group 'scala) (defcustom scala-indent:indent-value-expression nil "Whether or not to indent multi-line value expressions, with one extra step. When true, indenting will be val x = try { some() } catch { case e => other } finally { clean-up() } When nil, the same will indent as val x = try { some() } catch { case e => other } finally { clean-up() } " :type 'boolean :group 'scala) (defcustom scala-indent:align-parameters nil "Whether or not to indent parameter lists so that next parameter lines always align under the first parameter. When non-nil, indentation will be def foo(x: Int, y: List[Int] z: Int) val x = foo(1, List(1, 2, 3) map (i => i + 1 ), 2) When nil, the same will indent as def foo(x: Int, y: List[Int] z: Int) val x = foo(1, List(1, 2, 3) map (i => i + 1 ), 2) " :type 'boolean :safe #'booleanp :group 'scala) (defcustom scala-indent:align-forms nil "Whether or not to align 'else', 'yield', 'catch', 'finally' below their respective expression start. When non-nil, identing will be val x = if (foo) bar else zot when nil, the same will indent as val x = if (foo) bar else zot " :type 'boolean :group 'scala) (defconst scala-indent:eager-strategy 0 "See 'scala-indent:run-on-strategy'") (defconst scala-indent:operator-strategy 1 "See 'scala-indent:run-on-strategy'") (defconst scala-indent:reluctant-strategy 2 "See 'scala-indent:run-on-strategy'") (defconst scala-indent:keywords-only-strategy 3 "A strategy used internally by indent engine") (defcustom scala-indent:default-run-on-strategy 2 "What strategy to use for detecting run-on lines, i.e. lines that continue a statement from the previous line. Possible values are: 'reluctant', which marks only lines that begin with -- or that follow a line that ends with -- a reserved word that cannot start or end a line, such as 'with'. 'operators', which extends the previous strategy by marking also lines that begin with -- or that follow a line that ends with -- an operator character. For example, '+', '-', etc. 'eager', which marks all rows which could be run-ons, i.e. which are not ruled out by the language specification. " :type `(choice (const :tag "eager" ,scala-indent:eager-strategy) (const :tag "operators" ,scala-indent:operator-strategy) (const :tag "reluctant" ,scala-indent:reluctant-strategy)) :group 'scala) (make-variable-buffer-local 'scala-indent:effective-run-on-strategy) (defcustom scala-indent:add-space-for-scaladoc-asterisk t "When non-nil, a space will be added after a scaladoc asterisk, when it is added to an empty line." :type 'boolean :safe #'booleanp :group 'scala) (defcustom scala-indent:use-javadoc-style nil "When non-nil, multi-line comments are indented according to Javadoc style (i.e. indented to the first asterisk). This overrides the Scaladoc behavior of indenting comment lines to the second asterisk." :type 'boolean :safe #'booleanp :group 'scala) (defun scala-indent:run-on-strategy () "Returns the currently effecti run-on strategy" (or scala-indent:effective-run-on-strategy scala-indent:default-run-on-strategy scala-indent:eager-strategy)) (defun scala-indent:toggle-effective-run-on-strategy () "If effective run-on strategy is not set, it is set as follows: - if default is eager or operators, then it is set to reluctant - if default is reluctant, then it is set to eager. If it is set, it is nilled." (if scala-indent:effective-run-on-strategy (setq scala-indent:effective-run-on-strategy nil) (let ((new-strategy (cond ((= (scala-indent:run-on-strategy) scala-indent:reluctant-strategy) scala-indent:eager-strategy) ((or (= (scala-indent:run-on-strategy) scala-indent:operator-strategy) (= (scala-indent:run-on-strategy) scala-indent:eager-strategy)) scala-indent:reluctant-strategy)))) (setq scala-indent:effective-run-on-strategy new-strategy)))) (defun scala-indent:reset-effective-run-on-strategy () (setq scala-indent:effective-run-on-strategy nil)) (defun scala-indent:rotate-run-on-strategy () (interactive) (let ((new-strategy (cond ((= scala-indent:default-run-on-strategy scala-indent:reluctant-strategy) scala-indent:operator-strategy) ((= scala-indent:default-run-on-strategy scala-indent:operator-strategy) scala-indent:eager-strategy) ((= scala-indent:default-run-on-strategy scala-indent:eager-strategy) scala-indent:reluctant-strategy)))) (setq scala-indent:default-run-on-strategy new-strategy) ; (message "scala-indent:default-run-on-strategy set to %s" scala-indent:default-run-on-strategy) )) (defun scala-indent:backward-sexp-to-beginning-of-line () "Skip sexps backwards until reaches beginning of line (i.e. the point is at the first non whitespace or comment character). It does not move outside enclosin list. Returns the current point or nil if the beginning of line could not be reached because of enclosing list." (let ((code-beg (scala-lib:point-after (scala-syntax:beginning-of-code-line)))) (ignore-errors (while (> (point) code-beg) (scala-syntax:backward-sexp) (skip-syntax-backward ".") (when (< (point) code-beg) ;; moved to previous line, set new target (setq code-beg (scala-lib:point-after (scala-syntax:beginning-of-code-line)))))) (unless (> (point) code-beg) (point)))) (defun scala-indent:align-anchor () "Go to beginning of line, if a) scala-indent:align-parameters is nil or backward-sexp-to-beginning-of-line is non-nil. This has the effect of staying within lists if scala-indent:align-parameters is non-nil." (when (or (scala-indent:backward-sexp-to-beginning-of-line) (not scala-indent:align-parameters)) (back-to-indentation))) (defun scala-indent:value-expression-lead (start anchor &optional not-block-p) ;; calculate an indent lead. The lead is one indent step if there is ;; a '=' between anchor and start, otherwise 0. (if (and scala-indent:indent-value-expression (ignore-errors (save-excursion (let ((block-beg (if not-block-p start (nth 1 (syntax-ppss start))))) (goto-char anchor) (scala-syntax:has-char-before ?= block-beg))))) scala-indent:step 0)) ;;; ;;; Run-on ;;; (defconst scala-indent:mustNotTerminate-keywords-re (regexp-opt '("extends" "forSome" "match" "with") 'words) "Some keywords which occure only in the middle of an expression") (defconst scala-indent:mustNotTerminate-line-beginning-re (concat "\\(" scala-indent:mustNotTerminate-keywords-re "\\|:\\(" scala-syntax:after-reserved-symbol-re "\\)\\)") "All keywords and symbols that cannot terminate a expression and must be handled by run-on. Reserved-symbols not included.") (defconst scala-indent:mustTerminate-re (concat "\\([,;\u21D2]\\|=>?" scala-syntax:end-of-code-line-re "\\|\\s(\\|" scala-syntax:empty-line-re "\\)") "Symbols that must terminate an expression or start a sub-expression, i.e the following expression cannot be a run-on. This includes only parenthesis, '=', '=>', ',' and ';' and the empty line") (defconst scala-indent:mustNotContinue-re (regexp-opt '("abstract" "catch" "case" "class" "def" "do" "else" "final" "finally" "for" "if" "implicit" "import" "lazy" "new" "object" "override" "package" "private" "protected" "return" "sealed" "throw" "trait" "try" "type" "val" "var" "while" "yield" "inline") 'words) "Words that we don't want to continue the previous line") (defconst scala-indent:mustBeContinued-line-end-re (concat "\\(" scala-syntax:other-keywords-unsafe-re "\\|:" scala-syntax:end-of-code-line-re "\\)") "All keywords and symbols that cannot terminate a expression and are infact a sign of run-on. Reserved-symbols not included.") (defun scala-indent:run-on-p (&optional point strategy) "Returns t if the current point is in the middle of an expression" ;; use default strategy if none given (when (not strategy) (setq strategy (scala-indent:run-on-strategy))) (save-excursion (when point (goto-char point)) (unless (eobp) ;; Note: ofcourse this 'cond' could be written as one big boolean ;; expression, but I doubt that would be so readable and ;; maintainable (cond ;; NO: this line starts with close parenthesis ((= (char-syntax (char-after)) ?\)) nil) ;; NO: the previous line must terminate ((save-excursion (scala-syntax:skip-backward-ignorable) (or (bobp) (scala-syntax:looking-back-empty-line-p) (scala-syntax:looking-back-token scala-indent:mustTerminate-re))) nil) ;; YES: in a region where newlines are disabled ((and (scala-syntax:newlines-disabled-p) (not (= strategy scala-indent:keywords-only-strategy))) t) ;; NO: this line starts with a keyword that starts a new ;; expression (e.g. 'def' or 'class') ((looking-at scala-indent:mustNotContinue-re) nil) ;; NO: this line is the start of value body ((scala-indent:body-p) nil) ;; YES: eager strategy can stop here, everything is a run-on if no ;; counter evidence ((= strategy scala-indent:eager-strategy) t) ;; YES: this line must not terminate because it starts with a ;; middle of expression keyword ((looking-at scala-indent:mustNotTerminate-line-beginning-re) t) ;; YES: end of prev line must not terminate ((let ((case-fold-search nil)) (scala-syntax:looking-back-token scala-indent:mustBeContinued-line-end-re)) t) ;; YES: this line starts with type param ((= (char-after) ?\[) t) ;; YES: this line starts with open paren and the expression ;; after all parens is a run-on ((and (= (char-after) ?\() (save-excursion (scala-syntax:forward-parameter-groups) (scala-syntax:skip-forward-ignorable) (or (= (char-after) ?=) (= (char-after) ?{) (scala-indent:run-on-p nil strategy)))) t) ;; NO: that's all for keywords-only strategy ((= strategy scala-indent:keywords-only-strategy) nil) ;; YES: this line starts with punctuation ((= (char-after) ?\.) t) ;; YES: prev line ended with punctuation ((scala-syntax:looking-back-token ".*[.]") t) ;; NO: that's all for reluctant-strategy ((= strategy scala-indent:reluctant-strategy) nil) ;; YES: this line starts with opchars ((save-excursion (< 0 (skip-chars-forward scala-syntax:opchar-group))) t) ;; YES: prev line ends with opchars ((save-excursion (scala-syntax:skip-backward-ignorable) (> 0 (skip-chars-backward scala-syntax:opchar-group))) t) ;; NO: else nil (only operator strategy should reach here) (t nil))))) (defun scala-indent:run-on-line-p (&optional point strategy) "Returns t if the current point (or point at 'point) is on a line that is a run-on from a previous line." (save-excursion (when point (goto-char point)) (scala-syntax:beginning-of-code-line) (scala-indent:run-on-p nil strategy))) (defun scala-indent:goto-run-on-anchor (&optional point strategy) "Moves back to the point whose column will be used as the anchor relative to which indenting for current point (or point 'point') is calculated. Returns the new point or nil if the point is not on a run-on line." (when (scala-indent:run-on-line-p point strategy) (when point (goto-char point)) (scala-syntax:beginning-of-code-line) (while (and (scala-indent:run-on-line-p nil strategy) (scala-syntax:skip-backward-ignorable) (scala-indent:backward-sexp-to-beginning-of-line))) (scala-indent:align-anchor) (point))) (defconst scala-indent:double-indent-re (concat (regexp-opt '("with" "extends" "forSome") 'words) "\\|:\\(" scala-syntax:after-reserved-symbol-re "\\)")) (defun scala-indent:resolve-run-on-step (start &optional anchor) "Resolves the appropriate indent step for run-on line at position 'start'" (save-excursion (goto-char anchor) (if (scala-syntax:looking-at-case-p) ;; case run-on lines get double indent, except '|' which get ;; special indents (progn (goto-char start) (- (* 2 scala-indent:step) (skip-chars-forward "|"))) (goto-char start) (cond ;; some keywords get double indent ((or (looking-at scala-indent:double-indent-re) (scala-syntax:looking-back-token scala-indent:double-indent-re)) (* 2 scala-indent:step)) ;; no indent if the previous line is just close parens ;; ((save-excursion ;; (scala-syntax:skip-backward-ignorable) ;; (let ((end (point))) ;; (scala-syntax:beginning-of-code-line) ;; (skip-syntax-forward ")") ;; (= (point) end))) ;; 0) ;; else normal indent (t (+ (if scala-indent:align-parameters 0 (scala-indent:value-expression-lead start anchor)) scala-indent:step)))))) (defconst scala-indent:forms-align-re (regexp-opt '("yield" "else" "catch" "finally") 'words)) (defun scala-indent:forms-align-p (&optional point) "Returns scala-syntax:beginning-of-code-line for the line on which current point (or point 'point') is, if the line starts with one of 'yield', 'else', 'catch' and 'finally', otherwise nil. Also, the previous line must not be with '}'" (save-excursion (when point (goto-char point)) (scala-syntax:beginning-of-code-line) (when (looking-at scala-indent:forms-align-re) (goto-char (match-beginning 0)) (point)))) (defun scala-indent:goto-forms-align-anchor (&optional point) "Moves back to the point whose column will be used as the anchor relative to which indenting of special words on beginning of the line on which point (or point 'point') is, or nul if not special word found. Special words include 'yield', 'else', 'catch' and 'finally'" (let ((special-beg (scala-indent:forms-align-p point))) (when special-beg (goto-char special-beg) (if (and (scala-syntax:looking-back-token "}") (save-excursion (goto-char (match-beginning 0)) (= (match-beginning 0) (scala-lib:point-after (scala-syntax:beginning-of-code-line))))) (goto-char (match-beginning 0)) (let ((anchor (cond ((looking-at "\\") ;; align with 'for' (if (scala-syntax:search-backward-sexp "\\") (point) (message "matching 'for' not found") nil)) ((looking-at "\\") ;; align with 'if' or 'else if' (if (scala-syntax:search-backward-sexp "\\") (if (scala-syntax:looking-back-token "\\") (goto-char (match-beginning 0)) (point)) nil)) ((looking-at "\\") ;; align with 'try' (if (scala-syntax:search-backward-sexp "\\") (point) (message "matching 'try' not found") nil)) ((looking-at "\\") ;; align with 'try' (if (scala-syntax:search-backward-sexp "\\") (point) (message "matching 'try' not found") nil))))) (if scala-indent:align-forms anchor (when anchor (scala-indent:align-anchor) (point)))))))) (defun scala-indent:resolve-forms-align-step (start anchor) (if scala-indent:align-forms 0 (scala-indent:value-expression-lead start anchor t))) ;;; ;;; Lists and enumerators ;;; (defun scala-indent:goto-list-anchor-impl (point) (goto-char point) ;; find the first element of the list (if (not scala-indent:align-parameters) (progn (back-to-indentation) (point)) (forward-comment (buffer-size)) (if (= (line-number-at-pos point) (line-number-at-pos)) (goto-char point) (beginning-of-line)) ;; align list with first non-whitespace character (skip-syntax-forward " ") (point))) (defun scala-indent:goto-list-anchor (&optional point) "Moves back to the point whose column will be used to indent list rows at current point (or point 'point'). Returns the new point or nil if the point is not in a list element > 1." (let ((list-beg (scala-syntax:list-p point))) (when list-beg (scala-indent:goto-list-anchor-impl list-beg)))) (defun scala-indent:resolve-list-step (start anchor) (if scala-indent:align-parameters 0 (scala-indent:resolve-block-step start anchor))) (defun scala-indent:for-enumerators-p (&optional point) "Returns the point after opening parentheses if the current point (or point 'point') is in a block of enumerators. Return nil if not in a list of enumerators or at the first enumerator." (unless point (setq point (point))) (save-excursion (goto-char point) (scala-syntax:beginning-of-code-line) (let ((state (syntax-ppss point))) (unless (or (eobp) (= (char-syntax (char-after)) ?\))) (when (and state (nth 1 state)) (goto-char (nth 1 state)) (when (scala-syntax:looking-back-token scala-syntax:for-re) (forward-char) (forward-comment (buffer-size)) (when (< (point) point) (1+ (nth 1 state))))))))) (defun scala-indent:goto-for-enumerators-anchor (&optional point) "Moves back to the point whose column will be used to indent for enumerator at current point (or point 'point'). Returns the new point or nil if the point is not in a enumerator element > 1." (let ((enumerators-beg (scala-indent:for-enumerators-p point))) (when enumerators-beg (scala-indent:goto-list-anchor-impl enumerators-beg)))) ;;; ;;; Body ;;; (defconst scala-indent:control-keywords-cond-re (regexp-opt '("if" "while" "for") 'words) "All the flow control keywords that are followed by a condition (or generators in the case of 'for') in parentheses.") (defconst scala-indent:control-keywords-other-re (regexp-opt '("else" "do" "yield" "try" "finally" "catch") 'words) "Other flow control keywords (not followed by parentheses)") (defconst scala-indent:control-keywords-re (concat "\\(" scala-indent:control-keywords-cond-re "\\|" scala-indent:control-keywords-other-re "\\)")) (defun scala-indent:body-p (&optional point) "Returns the position of '=' symbol, or one of the scala-indent:control-keywords-re or scala-indent:control-keywords-cond-re keywords if current point (or point 'point) is on a line that follows said symbol or keyword, or nil if not." (save-excursion (when point (goto-char point)) (scala-syntax:beginning-of-code-line) (or (scala-syntax:looking-back-token scala-syntax:body-start-re 3) (let ((case-fold-search nil)) (scala-syntax:looking-back-token scala-indent:control-keywords-other-re)) (progn ;; if, else if (when (scala-syntax:looking-back-token ")" 1) (goto-char (match-end 0)) (backward-list)) (when (scala-syntax:looking-back-token scala-indent:control-keywords-cond-re) (goto-char (match-beginning 0)) (when (and (looking-at "\\") (scala-syntax:looking-back-token "\\")) (goto-char (match-beginning 0))) (when (not scala-indent:align-forms) (scala-indent:align-anchor)) (point)))))) (defun scala-indent:goto-body-anchor (&optional point) (let ((declaration-end (scala-indent:body-p point))) (when declaration-end (goto-char declaration-end) (if (let ((case-fold-search nil)) (looking-at scala-indent:control-keywords-re)) (point) (when (scala-indent:backward-sexp-to-beginning-of-line) (scala-indent:goto-run-on-anchor nil scala-indent:keywords-only-strategy)) (scala-indent:align-anchor) (point))))) (defun scala-indent:resolve-body-step (start &optional anchor) (if (and (not (= start (point-max))) (= (char-after start) ?\{)) 0 (+ (scala-indent:value-expression-lead start anchor t) scala-indent:step))) ;;; ;;; Block ;;; (defun scala-indent:goto-block-anchor (&optional point) "Moves back to the point whose column will be used as the anchor for calculating block indent for current point (or point 'point'). Returns point or (point-min) if not inside a block." (let ((block-beg (nth 1 (syntax-ppss (scala-lib:point-after (beginning-of-line)))))) (when block-beg ;; check if the opening paren is the first on the line, ;; if so, it is the anchor. If not, then go back to the ;; start of the line (goto-char block-beg) (if (= (point) (scala-lib:point-after (scala-syntax:beginning-of-code-line))) (point) (goto-char (or (scala-syntax:looking-back-token scala-syntax:body-start-re 3) (point))) (scala-syntax:backward-parameter-groups) (when (scala-indent:backward-sexp-to-beginning-of-line) (scala-indent:goto-run-on-anchor nil scala-indent:keywords-only-strategy)) (scala-indent:align-anchor) (point))))) (defun scala-indent:resolve-block-step (start anchor) "Resolves the appropriate indent step for block line at position 'start' relative to the block anchor 'anchor'." (let ((lead (scala-indent:value-expression-lead start anchor))) (cond ;; at end of buffer ((= start (point-max)) (+ scala-indent:step lead)) ;; block close parentheses line up with anchor in normal case ((= (char-syntax (char-after start)) ?\)) (+ 0 lead)) ;; case-lines indent normally, regardless of where they are ((scala-syntax:looking-at-case-p start) (+ scala-indent:step lead)) ;; other than case-line in case-block get double indent ((save-excursion (goto-char (1+ (or (nth 1 (syntax-ppss start)) 0))) (forward-comment (buffer-size)) (and (scala-syntax:looking-at-case-p) (> (line-number-at-pos) (line-number-at-pos anchor)) (> start (match-beginning 0)))) (+ (* 2 scala-indent:step) lead)) ;; normal block line (t (+ scala-indent:step lead))))) ;;; ;;; Open parentheses ;;; (defun scala-indent:open-parentheses-line-p (&optional point) "Returns the position of the first character of the line, if the current point (or point 'point') is on a line that starts with an opening parentheses, or nil if not." (save-excursion (when point (goto-char point)) (scala-syntax:beginning-of-code-line) (if (looking-at "\\s(") (point) nil))) (defun scala-indent:goto-open-parentheses-anchor (&optional point) "Moves back to the point whose column will be used as the anchor for calculating opening parenthesis indent for the current point (or point 'point'). Returns point or nil, if line does not start with opening parenthesis." ;; There are five cases we need to consider: ;; 1. curry parentheses, i.e. 2..n parentheses groups. ;; 2. value body parentheses (follows '='). ;; 3. parameters, etc on separate line (who would be so mad?) ;; 4. non-value body parentheses (follows class, trait, new, def, etc). (let ((parentheses-beg (scala-indent:open-parentheses-line-p point))) (when parentheses-beg (goto-char parentheses-beg) (cond ;; case 1 ((and scala-indent:align-parameters (= (char-after) ?\() (scala-indent:run-on-p) (scala-syntax:looking-back-token ")" 1)) (scala-syntax:backward-parameter-groups) (let ((curry-beg (point))) (forward-char) (forward-comment (buffer-size)) (if (= (line-number-at-pos curry-beg) (line-number-at-pos)) (goto-char curry-beg) nil))) ;; case 2 ((scala-syntax:looking-back-token "=" 1) nil) ; let body rule handle it ;; case 4 ((and (= (char-after) ?\{) (scala-indent:goto-run-on-anchor nil scala-indent:keywords-only-strategy)) ; use customized strategy (point)) ;; case 3 ;;((scala-indent:run-on-p) ;; (scala-syntax:skip-backward-ignorable) ;; (back-to-indentation) ;; (point)) (t nil) )))) (defun scala-indent:resolve-open-parentheses-step (start anchor) "Resolves the appropriate indent step for an open paren anchored at 'anchor'." (cond ((scala-syntax:looking-back-token ")") ; (message "curry") 0) ((save-excursion (goto-char anchor) ;; find = (scala-syntax:has-char-before ?= start)) ; (message "=") scala-indent:step) (t ; (message "normal at %d" (current-column)) 0))) (defun scala-indent:goto-line-comment-anchor (&optional point) "Goto and return the position relative to which a line comment will be indented. This will be the start of the line-comment on previous line, if any." (let ((pos (point))) (when (save-excursion (when point (goto-char point)) (when (and (looking-at "\\s *//") (not (scala-syntax:looking-back-empty-line-p)) (forward-comment -1)) (setq pos (point)))) (goto-char pos)))) ;;; ;;; Indentation engine ;;; (defun scala-indent:apply-indent-rules (rule-indents &optional point) "Evaluates each rule, until one returns non-nil value. Returns the sum of the value and the respective indent step, or nil if nothing was applied." (when rule-indents (save-excursion (when point (goto-char point)) (let* ((pos (scala-syntax:beginning-of-code-line)) (rule-indent (car rule-indents)) (rule-statement (car rule-indent)) (indent-statement (cadr rule-indent)) (anchor (funcall rule-statement point))) (if anchor (progn (if scala-mode:debug-messages (message "indenting acording to %s at %d for pos %d for point %s" rule-statement anchor pos point)) (when (/= anchor (point)) (error (format "Assertion error: anchor=%d, point=%d" anchor (point)))) (+ (current-column) (save-excursion (if (functionp indent-statement) (funcall indent-statement pos anchor) (eval indent-statement))))) (scala-indent:apply-indent-rules (cdr rule-indents))))))) (defun scala-indent:calculate-indent-for-line (&optional point) "Calculate the appropriate indent for the current point or the point 'point'. Returns the new column, or nil if the indent cannot be determined." (or (scala-indent:apply-indent-rules `((scala-indent:goto-line-comment-anchor 0) (scala-indent:goto-open-parentheses-anchor scala-indent:resolve-open-parentheses-step) (scala-indent:goto-for-enumerators-anchor scala-indent:resolve-list-step) (scala-indent:goto-forms-align-anchor scala-indent:resolve-forms-align-step) (scala-indent:goto-list-anchor scala-indent:resolve-list-step) (scala-indent:goto-body-anchor scala-indent:resolve-body-step) (scala-indent:goto-run-on-anchor scala-indent:resolve-run-on-step) (scala-indent:goto-block-anchor scala-indent:resolve-block-step) ) point) 0)) (defun scala-indent:indent-line-to (column) "Indent the line to column and move cursor to the indent column, if it was at the left margin." (when column (if (<= (current-column) (current-indentation)) (indent-line-to column) (save-excursion (indent-line-to column))))) (make-variable-buffer-local 'scala-indent:previous-indent-pos) (defun scala-indent:remove-indent-from-previous-empty-line () "Handles removing of whitespace from a previosly indented code line that was left empty (i.e. whitespaces only). Also clears the scala-indent:previous-indent-pos variable that controls the process." (when (and scala-indent:previous-indent-pos (/= scala-indent:previous-indent-pos (point))) (save-excursion (beginning-of-line) (if (= scala-indent:previous-indent-pos (point)) (setq scala-indent:previous-indent-pos (when (looking-at "^\\s +$") (point))) (goto-char scala-indent:previous-indent-pos) (when (looking-at "^\\s +$") (delete-region (match-beginning 0) (match-end 0))) (setq scala-indent:previous-indent-pos nil))))) (defun scala-indent:indent-code-line (&optional strategy) "Indent a line of code. Expect to be outside of any comments or strings" (if strategy (setq scala-indent:effective-run-on-strategy strategy) (if (eq last-command this-command) (scala-indent:toggle-effective-run-on-strategy) (scala-indent:reset-effective-run-on-strategy))) ; (message "run-on-strategy is %s" (scala-indent:run-on-strategy)) (scala-indent:indent-line-to (scala-indent:calculate-indent-for-line)) (scala-lib:delete-trailing-whitespace) (setq scala-indent:previous-indent-pos (save-excursion (beginning-of-line) (when (looking-at "^\\s +$") (point))))) (defun scala-indent:indent-line (&optional strategy) "Indents the current line." (interactive "*") (let ((state (save-excursion (syntax-ppss (line-beginning-position))))) (if (not (nth 8 state)) ;; 8 = start pos of comment or string, nil if none (scala-indent:indent-code-line strategy) (scala-indent:indent-line-to (cond ((integerp (nth 4 state)) ;; 4 = nesting level of multi-line comment (scala-indent:scaladoc-indent (nth 8 state))) ((eq t (nth 3 state)) ;; 3 = t for multi-line string (or (save-excursion (beginning-of-line) (when (and (looking-at "\\s *|") (progn (goto-char (nth 8 state)) (looking-at "\\(\"\"\"\\)|"))) (goto-char (match-end 1)) (current-column))) (current-indentation))) (t (current-indentation))))))) (defun scala-indent:indent-with-reluctant-strategy () (interactive "*") (scala-indent:indent-line scala-indent:reluctant-strategy)) (defun scala-indent:scaladoc-indent (comment-start-pos) "Calculate indent for a multi-line comment. Scaladoc lines (starting with /**) are indented under the second aseterix. Other multi-line comment rows are indented undet the first asterisk. Note: start line is indented as code since the start of the comment is outside the comment region. " (save-excursion (goto-char comment-start-pos) (when (looking-at "/\\*+") (goto-char (if (and (not scala-indent:use-javadoc-style) (= (- (match-end 0) (match-beginning 0)) 3)) (- (match-end 0) 1) (+ (match-beginning 0) 1))) (current-column)))) (defun scala-indent:indent-on-parentheses () (when (and (= (char-syntax (char-before)) ?\)) (= (save-excursion (back-to-indentation) (point)) (1- (point)))) (scala-indent:indent-line))) (defconst scala-indent:indent-on-words-re (concat "^\\s *" (regexp-opt '("catch" "case" "else" "finally" "yield") 'words))) (defun scala-indent:indent-on-special-words () "This function is meant to be used with post-self-insert-hook. Indents the line if position is right after a space that is after a word that needs to be indented specially." ;; magic numbers used 4 = length of "case", 7 = length of "finally" (when (and (> (current-column) 4) (= (char-before) ?\s) (= (char-syntax (char-before (- (point) 1))) ?w) (save-excursion (backward-char) (looking-back scala-indent:indent-on-words-re 7)) (not (nth 8 (syntax-ppss)))) (scala-indent:indent-line-to (scala-indent:calculate-indent-for-line)))) (defun scala-indent:indent-on-scaladoc-asterisk () "This function is meant to be used with post-self-insert-hook. Indents the line if position is right after an asterisk in a multi-line comment block and there is only whitespace before the asterisk. If scala-indent:add-space-for-scaladoc-asterisk is t, also adds a space after the asterisk if the asterisk is the last character on the line." (let ((state (syntax-ppss))) (when (and (integerp (nth 4 state)) (looking-back "^\\s *\\*" (line-beginning-position))) (when scala-indent:add-space-for-scaladoc-asterisk (insert " ")) (scala-indent:indent-line-to (scala-indent:scaladoc-indent (nth 8 state)))))) (defun scala-indent:fix-scaladoc-close () "This function is meant to be used with post-self-insert-hook. Changes 'asterisk space slash' to 'asterisk slash' in a multi-line comment if position is right after that slash and scala-indent:add-space-for-scaladoc-asterisk is t." (let ((state (syntax-ppss))) (when (and scala-indent:add-space-for-scaladoc-asterisk (integerp (nth 4 state)) (looking-back "^\\s *\\*\\s /" (line-beginning-position))) (delete-region (- (point) 2) (- (point) 1))))) (defun scala-indent:insert-asterisk-on-multiline-comment () "Insert an asterisk at the end of the current line when at the beginning of a line inside a multi-line comment " (let* ((state (syntax-ppss)) (comment-start-pos (nth 8 state))) (when (and (integerp (nth 4 state)) ; Ensure that we're inside a scaladoc comment (string-match-p "^/\\*\\*[^\\*]" (buffer-substring-no-properties comment-start-pos (+ comment-start-pos 4))) ; Ensure that the previous line had a leading asterisk or was the comment start. (let ((prev-line (buffer-substring-no-properties (line-beginning-position 0) (line-end-position 0)))) (or (string-match-p "^\\s-*\\*" prev-line) (string-match-p "\\s-*/\\*\\*" prev-line)))) (skip-syntax-forward " ") (insert "*") (scala-indent:indent-on-scaladoc-asterisk)))) (defun scala-mode:indent-scaladoc-asterisk (&optional insert-space-p) (message "scala-mode:indent-scaladoc-asterisk has been deprecated")) (defun scala-indent:fixup-whitespace () "scala-mode version of `fixup-whitespace'" (interactive "*") (save-excursion (delete-horizontal-space) (if (or (looking-at "^\\|[]):.]") (save-excursion (forward-char -1) (if (nth 4 (syntax-ppss)) (looking-at "$\\|\\s(") (looking-at "$\\|[[(.]"))) (and (= (char-before) ?{) (= (char-after) ?}))) nil (insert ?\s)))) (defun scala-indent:join-line (&optional arg) "scala-mode version of `join-line', i.e. `delete-indentation'" (interactive "*P") (beginning-of-line) (if arg (forward-line 1)) (when (= (preceding-char) ?\n) (delete-region (point) (1- (point))) (delete-horizontal-space) (let ((state (syntax-ppss))) (cond ((and (integerp (nth 4 state)) ; nestable comment (i.e. with *) (looking-at " *\\*\\($\\|[^/]\\)") (save-excursion (goto-char (max (nth 8 state) (line-beginning-position))) (looking-at "\\s */?\\*"))) (delete-char 2)) ((and (nth 4 state) ; row comment (i.e. with //) (looking-at " //")) (delete-char 3)))) (scala-indent:fixup-whitespace))) (provide 'scala-mode-indent) emacs-scala-mode-1.1.0/scala-mode-lib.el000066400000000000000000000012461361107576700177170ustar00rootroot00000000000000;;; scala-mode-lib.el - Major mode for editing scala, common functions ;;; Copyright (c) 2012 Heikki Vesalainen ;;; For information on the License, see the LICENSE file (defvar scala-mode:debug-messages "If true, some debug messages may be printed printed." nil) (defmacro scala-lib:column-after (&rest body) `(save-excursion ,@body (current-column))) (defmacro scala-lib:point-after (&rest body) `(save-excursion ,@body (point))) (defun scala-lib:delete-trailing-whitespace () (save-excursion (end-of-line) (skip-syntax-backward " ") (unless (bolp) (delete-char (- (line-end-position) (point)))))) (provide 'scala-mode-lib) emacs-scala-mode-1.1.0/scala-mode-map.el000066400000000000000000000017511361107576700177270ustar00rootroot00000000000000;;; scala-mode-map.el - Major mode for editing scala, keyboard map ;;; Copyright (c) 2012 Heikki Vesalainen ;;; For information on the License, see the LICENSE file (require 'scala-mode-indent) (defvar scala-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map prog-mode-map) ;(substitute-key-definition 'delete-indentation 'scala-indent:join-line map global-map) map) "Local key map used for scala mode") (defun scala-mode-map:add-self-insert-hooks () (add-hook 'post-self-insert-hook 'scala-indent:indent-on-parentheses) (add-hook 'post-self-insert-hook 'scala-indent:indent-on-special-words) (add-hook 'post-self-insert-hook 'scala-indent:indent-on-scaladoc-asterisk) (add-hook 'post-self-insert-hook 'scala-indent:fix-scaladoc-close)) (defun scala-mode-map:add-remove-indent-hook () (add-hook 'post-command-hook 'scala-indent:remove-indent-from-previous-empty-line)) (provide 'scala-mode-map) emacs-scala-mode-1.1.0/scala-mode-paragraph.el000066400000000000000000000112221361107576700211110ustar00rootroot00000000000000;;; scala-mode-paragraph.el - Major mode for editing scala, paragraph ;;; detection and fill ;;; Copyright (c) 2012 Heikki Vesalainen For information on the License, ;;; see the LICENSE file ;;; Based on Scala Language Specification (SLS) Version 2.9 ;;; Provides paragraph navigation and fill for scaladocs and ;;; multi-line strings. (defconst scala-paragraph:paragraph-line-start-re (concat "\\(?:\\s-*" ; whitespace "\\(?://+\\|\\*\\|/\\*+" ; comment start "\\||\\)?" ; multi-line margin | "\\s-*\\)")) ; whitespace (defconst scala-paragraph:scaladoc-list-start-re (concat "\\(?:-" ; unordered liststs "\\|[1IiAa]\\." ; ordered lists "\\)\\s-*")) (defconst scala-paragraph:fill-first-line-re (concat "\\s-*\\(//+\\|\\*\\||\\)?\\s-*" "\\(?:" scala-paragraph:scaladoc-list-start-re "\\)?")) (defconst scala-paragraph:paragraph-start-re (concat scala-paragraph:paragraph-line-start-re "\\(?:$" ; empty line "\\|==*[^=]+==*[ ]*$" ; headings "\\|" scala-paragraph:scaladoc-list-start-re "\\|{{{" ; code block start "\\|}}}" ; code block end "\\|@[a-zA-Z]+\\>" ; annotations "\\)" "\\|\\(?:\\s-*\\*/\\)" ; end of comment )) (defconst scala-paragraph:paragraph-separate-re (concat scala-paragraph:paragraph-line-start-re "\\(?:$\\)" "\\|\\(?:\\s *\\*/\\)" ; end of comment )) (defun scala-paragraph:fill-function () (let (fill) (save-restriction (save-excursion (widen) (beginning-of-line) (cond ((looking-at "\\s-*/?\\*+\\s-*") (setq fill (replace-regexp-in-string "/\\*+" (lambda (str) (if (= (length str) 3) " *" " *")) (match-string-no-properties 0))) (goto-char (match-end 0)) (when (looking-at scala-paragraph:scaladoc-list-start-re) (setq fill (concat fill (make-string (- (match-end 0) (match-beginning 0)) ?\s))))) ((or (re-search-forward "\"\"\"|" (line-end-position) t) (and (eq (nth 3 (syntax-ppss)) t) (re-search-forward "^\\s-*|" (line-end-position) t))) (setq fill (concat (make-string (- (current-column) 1) ?\s) "|")) (setq fill (concat fill (make-string (skip-syntax-forward " ") ?\s))) (when (looking-at scala-paragraph:scaladoc-list-start-re) (setq fill (concat fill (make-string (- (match-end 0) (match-beginning 0)) ?\s)))))))) fill)) (defun scala-paragraph:fill-paragraph (&rest args) ;; move to inside multi-line comment or multi-line string, if outside (when (looking-at "\\s-*\\(?:/\\**\\|\"\"\"\\)\\s-*") (goto-char (match-end 0))) (let ((state (syntax-ppss)) (fill-paragraph-function ;; Avoid infinite recursion, set fill-paragraph-function to ;; nil if it is 'scala-paragraph:fill-paragraph (unless (eq fill-paragraph-function 'scala-paragraph:fill-paragraph) fill-paragraph-function))) (cond ((integerp (nth 4 state)) ;; mask multi-line comments and fill (save-restriction (narrow-to-region (nth 8 state) (save-excursion (goto-char (nth 8 state)) (if (forward-comment 1) (point) (point-max)))) (apply #'fill-paragraph args)) t) ((eq (nth 4 state) t) ;; line comment, let normal fill-function handle this nil) ((eq (nth 3 state) t) ;; mask multi-line strings and fill. (save-restriction (narrow-to-region (nth 8 state) (save-excursion (goto-char (nth 8 state)) (or (ignore-errors (forward-sexp) (point)) (point-max)))) (apply #'fill-paragraph args)) t) ;; TODO: fill lists ;; the rest should not be filled (code, etc) (t t)))) (provide 'scala-mode-paragraph) emacs-scala-mode-1.1.0/scala-mode-prettify-symbols.el000066400000000000000000000042521361107576700225050ustar00rootroot00000000000000;;; scala-mode-prettify-symbols.el --- Prettifying scala symbols -*- coding: utf-8; -*- ;; Copyright (c) 2016 Merlin Göttlinger ;; License: http://www.gnu.org/licenses/gpl.html ;;; Commentary: ;; ;; Suggested `prettify-symbols' for Scala editing, enable ;; `prettify-symbols-mode' and `setq' an alist of your choice ;; for `prettify-symbols-alist'. ;;; Code: (defconst scala-mode-pretty-bool-alist '(("<=" . ?≤) (">=" . ?≥) ("==" . ?≡) ("===" . ?≣) ("!" . ?¬) ("!=" . ?≢) ("&&" . ?∧) ("||" . ?∨) ("true" . ?⊤) ("false" . ?⊥) ("Boolean" . ?𝔹)) "Prettify rules for boolean related operations.") (defconst scala-mode-pretty-collection-alist '(("empty" . ?∅) ("sum" . ?∑) ("product" . ?∏) ("contains" . ?∍) ("forall" . ?∀) ("any" . ?∃) ("intersect" . ?∩) ("union" . ?∪) ("diff" . ?≏) ("subsetOf" . ?⊆) ("++" . ?⧺) ("::" . ?⸬) ("--" . ?╌)) "Prettify rules for collections related operations.") (defconst scala-mode-pretty-arrows-alist '(("->" . ?→) ("<-" . ?←) ("=>" . ?⇒) ("<=>" . ?⇔) ("-->" . ?⟶) ("<->" . ?↔) ("<--" . ?⟵) ("<-->" . ?⟷) ("==>" . ?⟹) ("<==" . ?⟸) ("<==>" . ?⟺) ("~>" . ?⇝) ("<~" . ?⇜)) "Prettify rules for arrow related code pieces.") (defconst scala-mode-pretty-misc-alist '(("Unit" . ?∅) ("Int" . ?ℤ) ("assert" . ?⊦) (":=" . ?≔)) "Prettify rules for other mixed code pieces.") (defconst scala-mode-pretty-categories-alist '(("flatMap" . ?⤜) (">>=" . ?⤜) ("bind" . ?⤜) (">>" . ?≫) ("followedBy" . ?≫) ("<+>" . ?⊕)) "Prettify rules for category theory related operators (for use with cats/scalaz/...).") (defcustom scala-prettify-symbols-alist (append scala-mode-pretty-bool-alist scala-mode-pretty-collection-alist scala-mode-pretty-arrows-alist scala-mode-pretty-misc-alist scala-mode-pretty-categories-alist) "All prettify rules to be applied in scala code." :type 'alist :group 'scala) (provide 'scala-mode-prettify-symbols) ;;; scala-mode-prettify-symbols.el ends here emacs-scala-mode-1.1.0/scala-mode-syntax.el000066400000000000000000001244741361107576700205100ustar00rootroot00000000000000;;;; scala-mode-syntax.el - Major mode for editing scala, syntax ;;; Copyright (c) 2012 Heikki Vesalainen ;;; For information on the License, see the LICENSE file ;;; Based on Scala Language Specification (SLS) Version 2.9 ;;;; ;;;; Scala syntax regular expressions ;;;; ;;; Based on the Scala language specification 2.9. Note: order is not ;;; the same as in the document, as here things are declared before ;;; used. ;;; A note on naming. Things that end with '-re' are regular ;;; expressions. Things that end with '-group' are regular expression ;;; character groups without the enclosing [], i.e. they are not ;;; regular expressions, but can be used in declaring one. ;; single letter matching groups (Chapter 1) (defconst scala-syntax:hexDigit-group "0-9A-Fa-f") (defconst scala-syntax:UnicodeEscape-re (concat "\\\\u[" scala-syntax:hexDigit-group "]\\{4\\}")) (defconst scala-syntax:upper-group "[:upper:]\\$") ;; missing _ to make ids work (defconst scala-syntax:upperAndUnderscore-group (concat "_" scala-syntax:upper-group )) (defconst scala-syntax:lower-group "[:lower:]") (defconst scala-syntax:letter-group (concat scala-syntax:lower-group scala-syntax:upper-group)) ;; TODO: add Lt, Lo, Nl (defconst scala-syntax:digit-group "0-9") (defconst scala-syntax:letterOrDigit-group (concat scala-syntax:upperAndUnderscore-group scala-syntax:lower-group scala-syntax:digit-group)) (defconst scala-syntax:opchar-safe-group "!%&*+/?\\\\^|~-") ;; TODO: Sm, So (defconst scala-syntax:opchar-unsafe-group "#:<=>@") (defconst scala-syntax:opchar-group (concat scala-syntax:opchar-unsafe-group scala-syntax:opchar-safe-group)) ;; Scala delimiters (Chapter 1), but no quotes (defconst scala-syntax:delimiter-group ".,;") ;; Integer Literal (Chapter 1.3.1) (defconst scala-syntax:nonZeroDigit-group "1-9") (defconst scala-syntax:octalDigit-group "0-7") (defconst scala-syntax:decimalNumeral-re (concat "0" "\\|[" scala-syntax:nonZeroDigit-group "][" scala-syntax:digit-group "]*")) (defconst scala-syntax:hexNumeral-re (concat "0x[" scala-syntax:hexDigit-group "]+")) (defconst scala-syntax:octalNumeral-re (concat "0[" scala-syntax:octalDigit-group "]+")) (defconst scala-syntax:integerLiteral-re (concat "-?" ;; added from definition of literal "\\(" scala-syntax:hexNumeral-re "\\|" scala-syntax:octalNumeral-re "\\|" scala-syntax:decimalNumeral-re "\\)[Ll]?")) ;; Floating Point Literal (Chapter 1.3.2) (defconst scala-syntax:exponentPart-re (concat "\\([eE][+-]?[" scala-syntax:digit-group "]+\\)")) (defconst scala-syntax:floatType-re "[fFdD]") (defconst scala-syntax:floatingPointLiteral-re (concat "-?" ;; added from definition of literal "\\([" scala-syntax:digit-group "]+\\.[" scala-syntax:digit-group "]*" scala-syntax:exponentPart-re "?" scala-syntax:floatType-re "?" "\\|" "\\.[" scala-syntax:digit-group "]+" scala-syntax:exponentPart-re "?" scala-syntax:floatType-re "?" "\\|" "[" scala-syntax:digit-group "]+" scala-syntax:exponentPart-re "\\|" "[" scala-syntax:digit-group "]+" scala-syntax:floatType-re "\\)")) (defconst scala-syntax:number-safe-start-re (concat "[^_" scala-syntax:letter-group "]")) ;; Boolean Literals (Chapter 1.3.3) (defconst scala-syntax:booleanLiteral-re "true|false") ;; Escape Sequences (Chapter 1.3.6) (defconst scala-syntax:escapeSequence-re "\\\\['btnfr\"\\\\]") ;; Octal Escape Sequences (Chapter 1.3.6) (defconst scala-syntax:octalEscape-re (concat "\\\\[" scala-syntax:octalDigit-group "\\]\\{1,3\\}")) ;; Character Literals (Chapter 1.3.4) (defconst scala-syntax:characterLiteral-re (concat "\\('\\)\\(" "[^\\\\]" ;; should be just printable char, but this is faster "\\|" scala-syntax:escapeSequence-re "\\|" scala-syntax:octalEscape-re "\\|" scala-syntax:UnicodeEscape-re "\\)\\('\\)")) (defconst scala-syntax:string-escape-re (concat scala-syntax:escapeSequence-re "\\|" scala-syntax:octalEscape-re "\\|" scala-syntax:UnicodeEscape-re)) ;; String Literals (Chapter 1.3.5) (defconst scala-syntax:stringElement-re (concat "\\(" "[^\n\"\\\\]" "\\|" scala-syntax:string-escape-re "\\)")) (defconst scala-syntax:oneLineStringLiteral-re (concat "\\(\"\\)" scala-syntax:stringElement-re "*\\(\"\\)")) (defconst scala-syntax:multiLineStringLiteral-start-re "\\(\"\\)\"\"\\(\"?\"?[^\"]\\)*") (defconst scala-syntax:multiLineStringLiteral-end-re "\"\"+\\(\"\\)") (defconst scala-syntax:multiLineStringLiteral-re (concat scala-syntax:multiLineStringLiteral-start-re scala-syntax:multiLineStringLiteral-end-re)) (defconst scala-syntax:stringLiteral-re (concat "\\(" scala-syntax:multiLineStringLiteral-re "\\|" scala-syntax:oneLineStringLiteral-re "\\)" )) ;; If you change this or any of the used regex, be sure to ;; maintain this or update propertize function accordingly: ;; group 1 = char start, 3 = char end ;; group 4 = multi-line string start, 6 = end ;; group 7 = string start, 9 = end (defconst scala-syntax:relaxed-char-and-string-literal-re (concat scala-syntax:characterLiteral-re "\\|" scala-syntax:multiLineStringLiteral-start-re "\\(?:" scala-syntax:multiLineStringLiteral-end-re "\\)?" "\\|\\(\"\\)" "\\(\\\\.\\|[^\"\n\\]\\)*" "\\(\"\\)")) ;; Identifiers (Chapter 1.1) (defconst scala-syntax:op-re (concat "[" scala-syntax:opchar-group "]+" )) (defconst scala-syntax:idrest-re ;; Eagerness of regexp causes problems with _. The following is a workaround, ;; but the resulting regexp matches only what SLS demands. (concat "\\(" "[_]??" "[" scala-syntax:letter-group scala-syntax:digit-group "]+" "\\)*" "\\(" "_+" scala-syntax:op-re "\\|" "_" "\\)?")) (defconst scala-syntax:varid-re (concat "[" scala-syntax:lower-group "]" scala-syntax:idrest-re)) (defconst scala-syntax:capitalid-re (concat "[" scala-syntax:upperAndUnderscore-group "]" scala-syntax:idrest-re)) ;; alphaid introduce by SIP11 (defconst scala-syntax:alphaid-re (concat "\\(" "[" scala-syntax:lower-group scala-syntax:upperAndUnderscore-group "]" scala-syntax:idrest-re "\\)")) (defconst scala-syntax:plainid-re (concat "\\(" scala-syntax:alphaid-re "\\|" scala-syntax:op-re "\\)")) ;; stringlit is referred to, but not defined Scala Language Specification 2.9 ;; we define it as consisting of anything but '`' and newline (defconst scala-syntax:stringlit-re "[^`\n\r]") (defconst scala-syntax:quotedid-re (concat "`" scala-syntax:stringlit-re "+`")) (defconst scala-syntax:id-re (concat "\\(" scala-syntax:plainid-re "\\|" scala-syntax:quotedid-re "\\)")) (defconst scala-syntax:id-first-char-group (concat scala-syntax:lower-group scala-syntax:upperAndUnderscore-group scala-syntax:opchar-group)) ;; Symbol literals (Chapter 1.3.7) (defconst scala-syntax:symbolLiteral-re ;; must end with non-' to not conflict with scala-syntax:characterLiteral-re (concat "\\('" scala-syntax:plainid-re "\\)\\([^']\\|$\\)")) ;; Literals (Chapter 1.3) (defconst scala-syntax:literal-re (concat "\\(" scala-syntax:integerLiteral-re "\\|" scala-syntax:floatingPointLiteral-re "\\|" scala-syntax:booleanLiteral-re "\\|" scala-syntax:characterLiteral-re "\\|" scala-syntax:stringLiteral-re "\\|" scala-syntax:symbolLiteral-re "\\|" "null" "\\)")) (defconst scala-syntax:interpolation-re (concat "\\(" "\\$" scala-syntax:id-re "\\|" "\\${[^}\n\\\\]*}" "\\)")) (defun scala-syntax:interpolation-matcher (end) (let* ((pos nil) (syntax nil) (str-start nil) (char-before-str nil)) (while (and (setq pos (re-search-forward scala-syntax:interpolation-re end t)) (setq syntax (syntax-ppss pos)) (if (nth 3 syntax) ;; "is string" (progn (setq str-start (nth 8 syntax)) ;; s"foo" ;; ^-- `char-before-str', must be identifier (setq char-before-str (char-after (1- str-start))) ;; break if match (null (string-match-p scala-syntax:id-re (string char-before-str)))) t))) ;; keep going pos)) ;; Paths (Chapter 3.1) ;; emacs has a problem with these regex, don't use them ;; (defconst scala-syntax:classQualifier-re (concat "[[]" scala-syntax:id-re "[]]")) ;; (defconst scala-syntax:stableId-re ;; (concat "\\(\\(" "this" ;; "\\|" "super" scala-syntax:classQualifier-re ;; "\\|" scala-syntax:id-re ;; "\\)\\.\\)*" ;; scala-syntax:id-re)) ;; (defconst scala-syntax:path-re ;; (concat "\\(" scala-syntax:stableId-re ;; "\\|" "\\(" scala-syntax:id-re "\\." "\\)?" "this" "\\)")) (defun scala-syntax:looking-at-super () (save-excursion (when (looking-at "\\") (let ((beg (match-beginning 0))) (when (and (goto-char (match-end 0)) (or (when (= (char-after) ?.) (forward-char) t) (and (when (and (not (eobp)) (= (char-after) ?\[)) (forward-char) t) (progn (scala-syntax:skip-forward-ignorable) (looking-at scala-syntax:id-re)) (progn (goto-char (match-end 0)) (scala-syntax:skip-forward-ignorable) (when (and (not (eobp)) (= (char-after) ?\])) (forward-char) t)) (when (and (not (eobp)) (= (char-after) ?.)) (forward-char) t))) (looking-at scala-syntax:id-re)) (set-match-data `(,beg ,(match-end 0))) t))))) (defun scala-syntax:looking-at-stableIdOrPath (&optional path-p beg) (unless beg (setq beg (point))) (save-excursion (cond ((looking-at "\\") (goto-char (match-end 0)) (if (and (not (eobp)) (= (char-after) ?.)) (progn (forward-char) (scala-syntax:looking-at-stableIdOrPath path-p beg)) path-p)) ((or (scala-syntax:looking-at-super) (and (not (or (looking-at scala-syntax:keywords-unsafe-re) (scala-syntax:looking-at-reserved-symbol nil))) (looking-at scala-syntax:id-re))) (goto-char (match-end 0)) (if (and (not (eobp)) (= (char-after) ?.)) (progn (forward-char) (scala-syntax:looking-at-stableIdOrPath path-p beg)) (set-match-data `(,beg ,(match-end 0))) (point)))))) (defun scala-syntax:looking-at-simplePattern-beginning () (or (looking-at "[_(]") (looking-at scala-syntax:literal-re) (scala-syntax:looking-at-stableIdOrPath))) (defun scala-syntax:regexp-for-id (id) (let ((prefix-regex (if (string-match scala-syntax:alphaid-re id) "\\b" (concat "\\(^\\|[^" scala-syntax:opchar-group "]\\)"))) (suffix-regex (if (string-match scala-syntax:op-re (substring id -1 nil)) (concat "\\([^" scala-syntax:opchar-group "]\\|$\\)") "\\b"))) (concat prefix-regex id suffix-regex))) ;;; ;;; Other regular expressions ;;; (defconst scala-syntax:preamble-start-re "\#\!") (defconst scala-syntax:empty-line-re "^\\s *$") (defconst scala-syntax:comment-start-re "/[/*]") (defconst scala-syntax:end-of-code-line-re (concat "\\([ ]\\|$\\|" scala-syntax:comment-start-re "\\)") "A special regexp that can be concatenated to an other regular expression when used with scala-syntax:looking-back-token. Not meaningfull in other contexts.") (defconst scala-syntax:path-keywords-unsafe-re (regexp-opt '("super" "this") 'words)) (defconst scala-syntax:path-keywords-re (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:path-keywords-unsafe-re "\\)")) (defconst scala-syntax:value-keywords-unsafe-re (regexp-opt '("false" "null" "true") 'words)) (defconst scala-syntax:value-keywords-re (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:value-keywords-unsafe-re "\\)")) (defconst scala-syntax:other-keywords-unsafe-re (regexp-opt '("abstract" "case" "catch" "class" "def" "do" "else" "extends" "final" "finally" "for" "forSome" "if" "implicit" "import" "lazy" "match" "new" "object" "override" "package" "private" "protected" "return" "sealed" "throw" "trait" "try" "type" "val" "var" "while" "with" "yield" "inline") 'words)) (defconst scala-syntax:other-keywords-re (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:other-keywords-unsafe-re "\\)")) (defconst scala-syntax:keywords-unsafe-re (concat "\\(" scala-syntax:path-keywords-unsafe-re "\\|" scala-syntax:value-keywords-unsafe-re "\\|" scala-syntax:other-keywords-unsafe-re "\\)")) ;; TODO: remove ;; (defconst scala-syntax:keywords-re ;; (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:value-keywords-unsafe-re ;; "\\|" scala-syntax:path-keywords-unsafe-re ;; "\\|" scala-syntax:other-keywords-unsafe-re "\\)")) (defconst scala-syntax:after-reserved-symbol-underscore-re (concat "$\\|" scala-syntax:comment-start-re "\\|[^" scala-syntax:letterOrDigit-group "]")) (defconst scala-syntax:reserved-symbol-underscore-re ;; reserved symbol _ (concat "\\(^\\|[^" scala-syntax:letterOrDigit-group "]\\)" "\\(_\\)" "\\(" scala-syntax:after-reserved-symbol-underscore-re "\\)")) (defconst scala-syntax:reserved-symbols-unsafe-re ;; reserved symbols. The regexp is unsafe as it does not ;; check the context. "\\([:#@\u21D2\u2190]\\|=>?\\|<[:%!?\\-]\\|>:\\)" ) (defconst scala-syntax:double-arrow-unsafe-re "\\(=>\\|\u21D2\\)") (defconst scala-syntax:after-reserved-symbol-re (concat "\\($\\|" scala-syntax:comment-start-re "\\|[^" scala-syntax:opchar-group "]\\)")) (defconst scala-syntax:reserved-symbols-re ;; reserved symbols and XML starts ('") (defconst scala-syntax:for-re "\\") (defconst scala-syntax:class-or-object-re (regexp-opt '("class" "object") 'words)) ;;;; ;;;; Character syntax table and related syntax-propertize functions ;;;; ;;; The syntax table relies havily on the syntax-propertize-functions being ;;; run. Hence this syntax requires at least emacs 24, which introduced ;;; this new facility. (defvar scala-syntax:syntax-table nil "Syntax table used in `scala-mode' buffers.") (when (not scala-syntax:syntax-table) (let ((syntab (make-syntax-table))) ;; 1. start by reseting the syntax table: only (){}[] are ;; parentheses, so all others marked as parentheses in the parent ;; table must be marked as symbols, nothing is a punctuation ;; unless otherwise stated (map-char-table #'(lambda (key value) (when (or (= (syntax-class value) 4) ; open (= (syntax-class value) 5) ; close (= (syntax-class value) 1)) ; punctuation (modify-syntax-entry key "_" syntab))) (char-table-parent syntab)) ;; Below 'space', everything is either illegal or whitespace. ;; Consider as whitespace, unless otherwise stated below. (modify-syntax-entry '(0 . 32) " " syntab) ;; The scala parentheses (modify-syntax-entry ?\( "()" syntab) (modify-syntax-entry ?\[ "(]" syntab) (modify-syntax-entry ?\{ "(}" syntab) (modify-syntax-entry ?\) ")(" syntab) (modify-syntax-entry ?\] ")[" syntab) (modify-syntax-entry ?\} "){" syntab) ;; _ is upper-case letter, but will be modified to be symbol ;; constituent when in reserved symbol position by ;; syntax-propertize-function (modify-syntax-entry ?\_ "w" syntab) ;; by default all opchars are punctuation, but they will be ;; modified by syntax-propertize-function to be symbol ;; constituents when a part of varid or capitalid (dolist (char (mapcar 'identity "!#%&*+/:<=>?@^|~-\u21D2\u2190")) ;; TODO: Sm, So (modify-syntax-entry char "." syntab)) ;; for clarity, the \ is alone here and not in the string above (modify-syntax-entry ?\\ "." syntab) ;; scala strings cannot span lines, so we mark ;; " as punctuation, but do the real stuff ;; in syntax-propertize-function for properly ;; formatted strings. (modify-syntax-entry ?\" "." syntab) ;; backquote is given paired delimiter syntax so that ;; quoted ids are parsed as one sexp. Fontification ;; is done separately. (modify-syntax-entry ?\` "$" syntab) ;; ' is considered an expression prefix, since it can ;; both start a Symbol and is a char quote. It ;; will be given string syntax by syntax-propertize-function ;; for properly formatted char literals. (modify-syntax-entry ?\' "'" syntab) ;; punctuation as specified by SLS (modify-syntax-entry ?\. "." syntab) (modify-syntax-entry ?\; "." syntab) (modify-syntax-entry ?\, "." syntab) ;; comments ;; the `n' means that comments can be nested (modify-syntax-entry ?\/ ". 124b" syntab) (modify-syntax-entry ?\* ". 23n" syntab) (modify-syntax-entry ?\n "> b" syntab) (modify-syntax-entry ?\r "> b" syntab) (setq scala-syntax:syntax-table syntab))) (defun scala-syntax:propertize-extend-region (start end) "See syntax-propertize-extend-region-functions" ;; nothing yet nil) (defmacro scala-syntax:put-syntax-table-property (match-group value) "Add 'syntax-table entry 'value' to the region marked by the match-group 'match-group'" `(put-text-property (match-beginning ,match-group) (match-end ,match-group) 'syntax-table ,value)) (defun scala-syntax:propertize-char-and-string-literals (start end) "Mark start and end of character literals as well as one-line and multi-line string literals. One-line strings and characters use syntax class 7 (string quotes), while multi-line strings are marked with 15 (generic string delimiter). Multi-line string literals are marked even if they are unbalanced. One-line string literals have to be balanced to get marked. This means invalid characters and one-line strings will not be fontified." (let* ((string-state (nth 3 (syntax-ppss start))) (unbalanced-p (eq string-state t))) (if (and string-state (not unbalanced-p)) ;; a normal string is open, let's de-propertize (remove-text-properties start end '(syntax-table nil)) (save-excursion (goto-char start) ;; close the closing for the unbalanced multi-line literal (when (and unbalanced-p (re-search-forward scala-syntax:multiLineStringLiteral-end-re end t)) (scala-syntax:put-syntax-table-property 1 '(15 . nil))) ;; match any balanced one-line or multi-line literals (catch 'break (while (re-search-forward scala-syntax:relaxed-char-and-string-literal-re end t) ;; Expects the following groups: ;; group 1 = char start, 3 = char end ;; group 4 = multi-line string start, 6 = end ;; group 7 = string start, 9 = end (cond ((match-beginning 1) (scala-syntax:put-syntax-table-property 1 '(7 . nil)) (scala-syntax:put-syntax-table-property 3 '(7 . nil))) ((match-beginning 4) ;; start of multi-line literal (scala-syntax:put-syntax-table-property 4 '(15 . nil)) (if (match-beginning 6) ;; balanced multi-line (scala-syntax:put-syntax-table-property 6 '(15 . nil)) ;; un-balanced multi-line (throw 'break nil))) ((or ;; normal string, content is not empty (match-beginning 8) ;; empty string at line end (= (match-end 9) (line-end-position)) ;; no " after empty string (not (= (char-after (match-end 10)) ?\"))) (when (save-excursion (goto-char (match-beginning 7)) ;; really valid? (looking-at-p scala-syntax:oneLineStringLiteral-re)) (scala-syntax:put-syntax-table-property 7 '(7 . nil)) (scala-syntax:put-syntax-table-property 9 '(7 . nil)))) (t (throw 'break nil))))))))) (defun scala-syntax:propertize-shell-preamble (start end) "Mark a shell preamble (#!) at the beginning of a script as a line comment." (save-excursion (goto-char start) (when (and (= start 1) (looking-at scala-syntax:preamble-start-re)) (scala-syntax:put-syntax-table-property 0 '(11 . nil)) (end-of-line) (when (re-search-forward "\n" end t) (scala-syntax:put-syntax-table-property 0 '(12 . nil)))))) (defun scala-syntax:propertize-underscore-and-idrest (start end) "Mark all underscores (_) as symbol constituents (syntax 3) or upper case letter (syntax 2). Also mark opchars in idrest as symbol constituents (syntax 3)." (save-excursion (goto-char start) (while (re-search-forward "_" end t) (let ((match-beg (match-beginning 0)) (match-end (match-end 0))) (put-text-property match-beg match-end 'syntax-table (if (= match-beg (line-beginning-position)) (if (looking-at scala-syntax:after-reserved-symbol-underscore-re) '(3 . nil) ; symbol constituent '(2 . nil)) ; word syntax (save-excursion (goto-char (1- match-beg)) (if (looking-at scala-syntax:reserved-symbol-underscore-re) '(3 . nil) ; symbol constituent ;; check for opchars that should be marked as symbol constituents (3) (goto-char match-end) (when (looking-at scala-syntax:op-re) (scala-syntax:put-syntax-table-property 0 '(3 . nil))) '(3 . nil))))))))) ;; symbol constituent syntax (3) also for the '_' (defun scala-syntax:propertize-special-symbols (start end) (save-excursion (goto-char start) (while (re-search-forward (concat "[" scala-syntax:opchar-group "]" scala-syntax:op-re) end t) (let ((match-beg (match-beginning 0)) (match-end (match-end 0)) (match (match-string 0))) (unless (or (string-suffix-p "*/" match) (member match '(" (point) eol) (goto-char pos) (skip-syntax-forward " " eol) (point)))) (defun scala-syntax:looking-at-varid-p (&optional point) "Return true if looking-at varid, and it is not the start of a stableId" (save-excursion (when point (goto-char point)) (scala-syntax:skip-forward-ignorable) (let ((case-fold-search nil)) (when (looking-at scala-syntax:varid-re) (save-match-data (if (or (= (char-after (match-end 0)) ?.) (looking-at "\\<\\(this\\|super\\)\\>")) nil t)))))) (defun scala-syntax:looking-at-empty-line-p () (save-excursion (or (bolp) (skip-syntax-forward " >" (1+ (line-end-position)))) (looking-at scala-syntax:empty-line-re))) (defun scala-syntax:looking-at-reserved-symbol (re &optional point) (interactive) (unless re (setq re scala-syntax:reserved-symbols-unsafe-re)) (save-excursion (when point (goto-char point)) (scala-syntax:skip-forward-ignorable) (and (looking-at re) (goto-char (match-end 0)) (looking-at-p scala-syntax:after-reserved-symbol-re)))) (defun scala-syntax:looking-at-case-p (&optional point) (save-excursion (when point (goto-char point)) (scala-syntax:skip-forward-ignorable) (and (looking-at scala-syntax:case-re) (goto-char (match-end 0)) (scala-syntax:skip-forward-ignorable) (not (looking-at-p scala-syntax:class-or-object-re))))) (defun scala-syntax:looking-back-empty-line-p () "Return t if the previous line is empty" (save-excursion (skip-syntax-backward " " (line-beginning-position)) (and (bolp) (forward-line -1) (looking-at-p scala-syntax:empty-line-re)))) (defun scala-syntax:skip-forward-ignorable () "Moves forward over ignorable whitespace and comments. A completely empty line is not ignorable and will not be mobed over." (interactive) (save-match-data (while (and (not (scala-syntax:looking-at-empty-line-p)) (forward-comment 1))) (skip-syntax-forward " " (line-end-position)))) (defun scala-syntax:skip-backward-ignorable () "Move backwards over ignorable whitespace and comments. A completely empty line is not ignorable and will not be moved over. Returns the number of points moved (will be negative)." (save-match-data (while (and (not (scala-syntax:looking-back-empty-line-p)) (forward-comment -1))) (skip-syntax-backward " " (line-beginning-position)))) (defun scala-syntax:looking-at (re) "Return the end position of the matched re, if the current position is followed by it, or nil if not. All ignorable comments and whitespace are skipped before matching." (save-excursion (scala-syntax:skip-forward-ignorable) (looking-at re))) (defun scala-syntax:looking-back-token (re &optional max-chars) "Return the start position of the token matched by re, if the current position is preceeded by it, or nil if not. All ignorable comments and whitespace are ignored, i.e. does not search past an empty line. Expects to be outside of comment. A limit for the search is calculated based on max-chars. The function won't look further than max-chars starting after skipping any ignorable." (save-excursion ;; skip back all comments (scala-syntax:skip-backward-ignorable) (let ((end (point)) (limit (when max-chars (- (point) max-chars)))) ;; skip back punctuation or ids (words and related symbols and delimiters) (if (or (/= 0 (skip-chars-backward scala-syntax:delimiter-group limit)) (/= 0 (skip-syntax-backward "." limit)) (/= 0 (skip-syntax-backward "(" limit)) (/= 0 (skip-syntax-backward ")" limit)) (/= 0 (skip-syntax-backward "w_'$" limit))) (if (looking-at re) (point) nil) nil)))) (defun scala-syntax:backward-parameter-groups () "Move back over all parameter groups to the start of the first one." (save-match-data (while (scala-syntax:looking-back-token "[])]" 1) (backward-list)))) (defun scala-syntax:forward-parameter-groups () "Move back over all parameter groups to the end of the last one." (save-match-data (while (scala-syntax:looking-at "[[(]") (forward-list)))) (defun scala-syntax:forward-modifiers () "Move forward over any modifiers." (save-match-data (while (scala-syntax:looking-at scala-syntax:modifiers-re) (scala-syntax:forward-sexp) (when (scala-syntax:looking-at "[[]") (forward-list))))) (defun scala-syntax:looking-back-else-if-p () ;; TODO: rewrite using (scala-syntax:if-skipped (scala:syntax:skip-backward-else-if)) (save-excursion (if (and (scala-syntax:looking-back-token "\\s)" 1) (backward-list) (prog1 (scala-syntax:looking-back-token "if") (goto-char (match-beginning 0))) (prog1 (scala-syntax:looking-back-token "else") (goto-char (match-beginning 0)))) (point) nil))) (defun scala-syntax:newlines-disabled-p (&optional point) "Return true if newlines are disabled at the current point (or point 'point') as specified by SLS chapter 1.2" ;; newlines are disabled if ;; - in '()' or '[]' ;; - between 'case' and '=>' ;; - XML mode (not implemented here) (unless point (setq point (point))) (save-excursion (let* ((state (syntax-ppss point)) (parenthesisPos (nth 1 state))) (when parenthesisPos ;; if no parenthesis, then this cannot be a case block either (goto-char parenthesisPos) (or ;; the trivial cases of being inside ( or [ (= (char-after) ?\() (= (char-after) ?\[) ;; else we have to see about case (progn (forward-char) (forward-comment (buffer-size)) (skip-syntax-forward " >") (when (looking-at scala-syntax:case-re) (let ((limit (match-beginning 0))) (goto-char (or (nth 8 state) point)) ;; go to the start of => or 'case' (while (> (point) limit) (scala-syntax:backward-sexp) (when (or (looking-at scala-syntax:case-re) (scala-syntax:looking-at-reserved-symbol scala-syntax:double-arrow-unsafe-re)) (setq limit (point)))) ;; unless we found '=>', check if we found 'case' (but ;; 'case class' or 'case object') (unless (scala-syntax:looking-at-reserved-symbol scala-syntax:double-arrow-unsafe-re) (scala-syntax:forward-sexp) (and (<= (point) point) ;; check that we were inside in the first place (progn (scala-syntax:skip-forward-ignorable) (not (looking-at scala-syntax:class-or-object-re))))))))))))) (defun scala-syntax:forward-sexp () "Move forward one scala expression. It can be: parameter list (value or type), id, reserved symbol, keyword, block, or literal. Punctuation (.,;) and comments are skipped silently. Position is placed at the end of the skipped expression." (interactive) (syntax-propertize (point-max)) ;; emacs knows how to properly skip: lists, varid, capitalid, ;; strings, symbols, chars, quotedid. What we have to handle here is ;; most of all ids made of op chars ;; skip comments, whitespace and scala delimiter chars .,; so we ;; will be at the start of something interesting (forward-comment (buffer-size)) (while (< 0 (+ (skip-syntax-forward " ") (skip-chars-forward scala-syntax:delimiter-group)))) ;; emacs can handle everything but opchars (when (= (skip-syntax-forward ".") 0) (goto-char (or (scan-sexps (point) 1) (buffer-end 1))))) (defun scala-syntax:forward-token () "Move forward one scala token, comment word or string word. It can be: start or end of list (value or type), id, reserved symbol, keyword, block, or literal. Punctuation (.,;), comment delimiters and string delimiters are skipped silently. Position is placed at the end of the skipped token." (interactive) (syntax-propertize (point-max)) (skip-syntax-forward " >" (point-max)) (when (looking-at (concat "\\([#@:]\\|" scala-syntax:double-arrow-unsafe-re "\\|:>\\|<:\\)" scala-syntax:after-reserved-symbol-re)) (goto-char (match-end 1))) (let ((syntax (char-syntax (char-after))) (state (syntax-ppss))) (cond ((or (nth 4 state) (nth 3 state)) ;; inside a string or comment, skip words as normal unless that ;; would end up outside the string. Then leave point at end of ;; string delimiter. (let ((start (nth 8 state)) (end (save-excursion (forward-word) (point)))) (if (eq (nth 8 (save-excursion (syntax-ppss end))) start) (goto-char end) (while (eq (nth 8 (syntax-ppss)) start) (forward-char))))) ;; list start or end ((or (= syntax ?\)) (= syntax ?\()) (forward-char)) ;; comment or string start is skipped ((looking-at "\\(//\\|/\\*+\\|\"\\(\"\"\\)?\\)") (goto-char (match-end 1))) ;; otherwise forward-sexp (t (forward-sexp))))) (defun scala-syntax:backward-sexp () "Move backward one scala expression. It can be: parameter list (value or type), id, reserved symbol, keyword, block, or literal. Delimiters (.,;) and comments are skipped silently. Position is placed at the beginning of the skipped expression." (interactive) (syntax-propertize (point)) ;; for implementation comments, see scala-syntax:forward-sexp (forward-comment (- (buffer-size))) (while (> 0 (+ (skip-syntax-backward " ") (skip-chars-backward scala-syntax:delimiter-group)))) (when (= (skip-syntax-backward ".") 0) (goto-char (or (scan-sexps (point) -1) (buffer-end -1))) (backward-prefix-chars))) (defun scala-syntax:has-char-before (char end) (save-excursion (while (and (< (point) end) (or (bobp) (/= (char-before) char))) (scala-syntax:forward-sexp)) (when (= (char-before) char) (scala-syntax:skip-forward-ignorable) (> end (point))))) (defun scala-syntax:search-backward-sexp (re) "Searches backward sexps until it reaches re, empty line or ;. If re is found, point is set to beginning of re and the position is returned, otherwise nil is returned" (let ((found (save-excursion (while (not (or (bobp) (scala-syntax:looking-back-empty-line-p) (scala-syntax:looking-back-token "[;,]") (looking-at re))) (scala-syntax:backward-sexp)) (if (looking-at re) (point) nil)))) (when found (goto-char found)))) (defun scala-syntax:list-p (&optional point) "Returns the start of the list, if the current point (or point 'point') is on the first line of a list element > 1, or nil if not. A list must be either enclosed in parentheses or start with 'val', 'var' or 'import'." (save-excursion ;; first check that the previous line ended with ',' (when point (goto-char point)) (scala-syntax:beginning-of-code-line) (when (scala-syntax:looking-back-token "," 1) (goto-char (match-beginning 0)) (let ((parenpoint (nth 1 (syntax-ppss)))) (if (and parenpoint (or (= (char-after parenpoint) ?\() (= (char-after parenpoint) ?\[))) (1+ parenpoint) (ignore-errors ; catches when we get at parentheses (while (not (or (bobp) (looking-at scala-syntax:list-keywords-re) (scala-syntax:looking-back-empty-line-p) (scala-syntax:looking-back-token ";"))) (scala-syntax:backward-sexp))) (when (looking-at scala-syntax:list-keywords-re) (goto-char (match-end 0)))))))) ;; Functions to help with finding the beginning and end of scala definitions. (defconst scala-syntax:modifiers-re (regexp-opt '("override" "abstract" "final" "sealed" "implicit" "lazy" "private" "protected" "case") 'words)) (defconst scala-syntax:whitespace-delimeted-modifiers-re (concat "\\(?:" scala-syntax:modifiers-re "\\(?: *\\)" "\\)*")) (defconst scala-syntax:definition-words-re (mapconcat 'regexp-quote '("class" "object" "trait" "val" "var" "def" "type") "\\|")) (defun scala-syntax:build-definition-re (words-re) (concat " *" scala-syntax:whitespace-delimeted-modifiers-re words-re "\\(?: *\\)" "\\(?2:" scala-syntax:id-re "\\)")) (defconst scala-syntax:all-definition-re (scala-syntax:build-definition-re (concat "\\(?1:" scala-syntax:definition-words-re "\\)\\b"))) ;; Functions to help with beginning and end of definitions. (defun scala-syntax:backward-sexp-forcing () (condition-case ex (backward-sexp) ('error (backward-char)))) (defun scala-syntax:forward-sexp-or-next-line () (interactive) (cond ((looking-at "\n") (forward-line 1) (beginning-of-line)) (t (forward-sexp)))) (defun scala-syntax:beginning-of-definition () "This function may not work properly with certain types of scala definitions. For example, no care has been taken to support multiple assignments to vals such as val a, b = (1, 2) " (interactive) (let ((found-position (save-excursion (scala-syntax:backward-sexp-forcing) (scala-syntax:movement-function-until-re scala-syntax:all-definition-re 'scala-syntax:backward-sexp-forcing)))) (when found-position (progn (goto-char found-position) (back-to-indentation))))) (defun scala-syntax:end-of-definition () "This function may not work properly with certain types of scala definitions. For example, no care has been taken to support multiple assignments to vals such as val a, b = (1, 2) " (interactive) (re-search-forward scala-syntax:all-definition-re) (scala-syntax:find-brace-equals-or-next) (scala-syntax:handle-brace-equals-or-next)) (defun scala-syntax:find-brace-equals-or-next () (scala-syntax:go-to-pos (save-excursion (scala-syntax:movement-function-until-cond-function (lambda () (or (looking-at "[[:space:]]*[{=]") (looking-at scala-syntax:all-definition-re))) (lambda () (condition-case ex (scala-syntax:forward-sexp-or-next-line) ('error nil))))))) (defun scala-syntax:handle-brace-equals-or-next () (cond ((eobp) nil) ((looking-at "[[:space:]]*{") (forward-sexp)) ((looking-at "[[:space:]]*=") (scala-syntax:forward-sexp-or-next-line) (scala-syntax:handle-brace-equals-or-next)) ((looking-at scala-syntax:all-definition-re) nil) ((looking-at "[[:space:]]*\n[[:space:]]*}") (skip-syntax-forward "[[:space:]]*\n[[:space:]]*}")) (t (scala-syntax:forward-sexp-or-next-line) (scala-syntax:handle-brace-equals-or-next)))) (defun scala-syntax:movement-function-until-re (re movement-function) (save-excursion (scala-syntax:movement-function-until-cond-function (lambda () (looking-at re)) movement-function))) (defun scala-syntax:movement-function-until-cond-function (cond-function movement-function) (let ((last-point (point))) (if (not (funcall cond-function)) (progn (funcall movement-function) (if (equal last-point (point)) nil (scala-syntax:movement-function-until-cond-function cond-function movement-function))) last-point))) (defun scala-syntax:go-to-pos (pos) (when pos (goto-char pos))) (provide 'scala-mode-syntax) emacs-scala-mode-1.1.0/scala-mode.el000066400000000000000000000147361361107576700171630ustar00rootroot00000000000000;;; scala-mode.el --- Major mode for editing Scala ;; Copyright (c) 2012 Heikki Vesalainen ;; Homepage: https://github.com/hvesalai/emacs-scala-mode ;; Keywords: languages ;; Package-Version: 0.23 ;; Package-Requires: () ;;; Commentary: ;; ;;; Code: (require 'scala-mode-lib) (require 'scala-mode-syntax) (require 'scala-mode-paragraph) (require 'scala-mode-indent) (require 'scala-mode-fontlock) (require 'scala-mode-map) (require 'scala-mode-imenu) (require 'scala-mode-prettify-symbols) (defvar fixup-whitespace) ;; for compilation (defvar delete-indentation) ;; for compilation ;; Tested only for emacs 24 (unless (<= 24 emacs-major-version) (error (format "The Scala mode has been tested only on Emacs version 24.2 (and not your Emacs version %s.%s)" emacs-major-version emacs-minor-version))) (defgroup scala nil "A programming mode for the Scala language 2.9" :group 'languages) (defmacro scala-mode:make-local-variables (&rest quoted-names) (cons 'progn (mapcar #'(lambda (quoted-name) `(make-local-variable ,quoted-name)) quoted-names))) (defun scala-mode:find-tag () "Determine default tag to search for, based on text at point. If there is no plausible default, return nil." (let (from to) (when (and (progn ;; Look at text around `point'. (save-excursion (if (< 0 (skip-chars-backward scala-syntax:opchar-group)) (if (= (char-before) ?_) (skip-syntax-backward "w_")) (skip-syntax-backward "w_")) (setq from (point))) (save-excursion (skip-syntax-forward "w_.") (setq to (point))) (save-excursion (ignore-errors (scala-syntax:backward-sexp)) (setq from (max from (point)))) (save-excursion (goto-char from) (ignore-errors (scala-syntax:forward-sexp)) (setq to (min to (point)))) (> to from)) (save-excursion (goto-char from) (and (looking-at scala-syntax:id-re) (not (looking-at scala-syntax:keywords-unsafe-re))))) (buffer-substring-no-properties from to)))) (defun scala-mode:forward-sexp-function (&optional count) (unless count (setq count 1)) (if (< count 0) (dotimes (n (abs count)) (scala-syntax:backward-sexp)) (dotimes (n count) (scala-syntax:forward-sexp)))) ;;;###autoload (defun scala-mode:set-scala-syntax-mode () "Sets the syntax-table and other related variables for the current buffer to those of scala-mode. Can be used to make some other major mode (such as sbt-mode) use scala syntax-table." (set-syntax-table scala-syntax:syntax-table) (scala-mode:make-local-variables 'syntax-propertize-function 'parse-sexp-lookup-properties 'forward-sexp-function) (add-hook 'syntax-propertize-extend-region-functions 'scala-syntax:propertize-extend-region) (setq syntax-propertize-function 'scala-syntax:propertize parse-sexp-lookup-properties t forward-sexp-function 'scala-mode:forward-sexp-function)) ;;;###autoload (defun scala-mode:goto-start-of-code () "Go to the start of the real code in the file: object, class or trait." (interactive) (let* ((case-fold-search nil)) (search-forward-regexp "\\([[:space:]]+\\|^\\)\\(class\\|object\\|trait\\)" nil t) (move-beginning-of-line nil))) ;;;###autoload (define-derived-mode scala-mode prog-mode "Scala" "Major mode for editing scala code. When started, runs `scala-mode-hook'. \\{scala-mode-map}" :syntax-table scala-syntax:syntax-table ; :group ; :abbrev (scala-mode:make-local-variables 'post-self-insert-hook 'syntax-propertize-function 'font-lock-syntactic-face-function 'font-lock-defaults 'paragraph-start 'paragraph-separate 'parse-sexp-lookup-properties 'fill-paragraph-function 'adaptive-fill-function 'adaptive-fill-first-line-regexp 'comment-start 'comment-end 'comment-start-skip 'comment-column 'comment-multi-line 'forward-sexp-function 'find-tag-default-function 'indent-line-function 'fixup-whitespace 'delete-indentation 'indent-tabs-mode 'imenu-create-index-function 'beginning-of-defun-function 'end-of-defun-function) (add-hook 'syntax-propertize-extend-region-functions 'scala-syntax:propertize-extend-region) (setq scala-mode:debug-messages nil syntax-propertize-function 'scala-syntax:propertize parse-sexp-lookup-properties t ;; TODO: font-lock font-lock-defaults '(scala-font-lock:keywords nil) font-lock-syntactic-face-function 'scala-font-lock:syntactic-face-function ;; TODO: beginning-of-defun-function, end-of-defun-function ;; comments paragraph-start scala-paragraph:paragraph-start-re paragraph-separate scala-paragraph:paragraph-separate-re fill-paragraph-function 'scala-paragraph:fill-paragraph adaptive-fill-function 'scala-paragraph:fill-function adaptive-fill-first-line-regexp scala-paragraph:fill-first-line-re comment-start "// " comment-end "" comment-start-skip "\\(//+\\|/\\*+\\)[ \t]*" comment-column 0 comment-multi-line t forward-sexp-function 'scala-mode:forward-sexp-function find-tag-default-function 'scala-mode:find-tag indent-line-function 'scala-indent:indent-line fixup-whitespace 'scala-indent:fixup-whitespace delete-indentation 'scala-indent:join-line indent-tabs-mode nil beginning-of-defun-function #'scala-syntax:beginning-of-definition end-of-defun-function #'scala-syntax:end-of-definition imenu-create-index-function #'scala-imenu:create-imenu-index) (use-local-map scala-mode-map) ;; add indent functionality to some characters (scala-mode-map:add-remove-indent-hook) (scala-mode-map:add-self-insert-hooks)) ;; Attach .scala files to the scala-mode ;;;###autoload (progn (add-to-list 'auto-mode-alist '("\\.\\(scala\\|sbt\\)\\'" . scala-mode)) (modify-coding-system-alist 'file "\\.\\(scala\\|sbt\\)\\'" 'utf-8)) (provide 'scala-mode) ;;; scala-mode.el ends here emacs-scala-mode-1.1.0/test/000077500000000000000000000000001361107576700156005ustar00rootroot00000000000000emacs-scala-mode-1.1.0/test/scala-mode-test.el000066400000000000000000000120651361107576700211100ustar00rootroot00000000000000(defun smt:test (line exps expf) "line - line of scala code exps - expected codes of syntax class expf - expected font-locks" (let ((line-length (length line))) (with-temp-buffer (insert (format "package ensime object Ensime { %s }" line)) (scala-mode) (font-lock-ensure) (re-search-backward (regexp-opt `(,line)) nil t) (let ((end-point (+ (point) line-length)) (acc-syntax "") (acc-font "")) (while (< (point) end-point) (setq acc-syntax (concat acc-syntax (number-to-string (syntax-class (syntax-after (point)))))) (setq acc-font (concat acc-font (font-lock-to-string (get-text-property (point) 'face)))) (forward-char)) (should (equal acc-syntax exps)) (should (equal acc-font expf)))))) (defun font-lock-to-string (font-lock) (pcase font-lock (`nil "-") ('font-lock-constant-face "C") ('font-lock-variable-name-face "V") ('font-lock-keyword-face "K") ('font-lock-comment-face "O") ('font-lock-comment-delimiter-face "D") ('font-lock-doc-face "U") ('font-lock-type-face "T") ('font-lock-string-face "S") (_ "?"))) (ert-deftest smt:syntax-class-and-font-lock-test-1 () (smt:test "val `tvw xyz/*` = `abc def/*` + 123 /* comment `abc` abc */ + 456" "22203333333333301033333333333010222011022222220333330222011010222" "KKK-VVVVVVVVVVV-K---------------CCC-DDDOOOOOOOOOOOOOOOOOOOO---CCC")) (ert-deftest smt:syntax-class-and-font-lock-test-2 () (smt:test "val |+| = 123" "2220333010222" "KKK-VVV-K-CCC")) (ert-deftest smt:syntax-class-and-font-lock-test-3 () (smt:test "val a_|+| = 123" "222023333010222" "KKK-VVVVV-K-CCC")) (ert-deftest smt:syntax-class-and-font-lock-test-4 () (smt:test "val a = 123 /** hello */" "222020102220111022222011" "KKK-V-K-CCC-UUUUUUUUUUUU")) (ert-deftest smt:syntax-class-and-font-lock-test-5 () (smt:test "val a = hello" "2220201012212222211221" "KKK-V-K---------------")) (ert-deftest smt:syntax-class-and-font-lock-test-6 () (smt:test "// val |--| = 123" "11022203333010222" "DDDOOOOOOOOOOOOOO")) (ert-deftest smt:syntax-class-and-font-lock-test-7 () (smt:test "val xs = 1 :: 2 :: Nil" "2220220102033020330222" "KKK-VV-K-C----C----CCC")) (ert-deftest smt:syntax-class-and-font-lock-test-8 () (smt:test "val xs = 1:: 2 :: Nil" "222022010211020330222" "KKK-VV-K-C---C----CCC")) (ert-deftest smt:syntax-class-and-font-lock-test-9 () (smt:test "val xs = 1 ::2 :: Nil" "222022010201120330222" "KKK-VV-K-C---C----CCC")) (ert-deftest smt:syntax-class-and-font-lock-test-10 () (smt:test "case a :: (2) :: Nil" "22220203304250330222" "KKKK-V-TT--C--CC-TTT")) (ert-deftest smt:syntax-class-and-font-lock-test-11 () (smt:test "abc :<: def" "22203330222" "--------KKK")) (ert-deftest smt:syntax-class-and-font-lock-test-12 () (smt:test "Foo" "222121" "CCC-C-")) (ert-deftest smt:syntax-class-and-font-lock-test-13 () (smt:test "class X[T<:Mapper[T]](t: T){}" "22222024211222222425542102545" "KKKKK-T-CKKCCCCCC-C----K-T---")) (ert-deftest smt:syntax-class-and-font-lock-test-14 () (smt:test "class X[T <: Mapper[T]](t: T){}" "2222202420330222222425542102545" "KKKKK-T-C-KK-CCCCCC-C----K-T---")) (ert-deftest smt:syntax-class-and-font-lock-test-15 () (smt:test "val c = /* hello */ 20" "2220201011022222011022" "KKK-V-K-DDDOOOOOOOO-CC")) (ert-deftest smt:syntax-class-and-font-lock-test-16 () (smt:test "val c = /* hello **/ 20" "22202010110222220111022" "KKK-V-K-DDDOOOOOOOOO-CC")) (ert-deftest smt:syntax-class-and-font-lock-test-17 () (smt:test "val c = /**** hello */ 20" "2220201011111022222011022" "KKK-V-K-DDDDDDOOOOOOOO-CC")) (ert-deftest smt:syntax-class-and-font-lock-test-18 () (smt:test "val c = //**** hello */ 20" "22202010111111022222011022" "KKK-V-K-DDOOOOOOOOOOOOOOOO")) (ert-deftest smt:syntax-class-and-font-lock-test-19 () (smt:test "val c = 1 /////////// big comment" "222020102011111111111022202222222" "KKK-V-K-C-DDDDDDDDDDDDOOOOOOOOOOO")) (ert-deftest smt:syntax-class-and-font-lock-test-20 () (smt:test "val c = s\"result $sum\"" "2220201027222222012227" "KKK-V-K--SSSSSSSSVVVVS")) (ert-deftest smt:syntax-class-and-font-lock-test-21 () (smt:test "val c = s\"$sum-123\"" "2220201027122212227" "KKK-V-K--SVVVVSSSSS")) (ert-deftest smt:syntax-class-and-font-lock-test-22 () (smt:test "val c = s\"${sum.getOrElse(\"\")} - $sum\"" "22202010271422212222222224775501012227" "KKK-V-K--SSSSSSSSSSSSSSSSSSSSSSSSSSSSS")) (ert-deftest smt:syntax-class-and-font-lock-test-23 () "Test that `[!%&*+/?\\\\^|~-#:<=>@]\*/` will be treated as punctuation and _not_ a symbol. Doing so would cause comment strings such as `/* Comment &*/` to not be recognized as a delimiter, causing the entire file to treated as a comment. A concrete example may be viewed at https://github.com/scala/scala/blob/v2.11.11/src/reflect/scala/reflect/internal/Symbols.scala#L863" (smt:test "/* &*/" "110111" "DDDOOO")) emacs-scala-mode-1.1.0/test/test-helper.el000066400000000000000000000000261361107576700203540ustar00rootroot00000000000000(require 'scala-mode)