summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ert-runner1
-rw-r--r--.gitignore3
-rw-r--r--AUTHORS17
-rw-r--r--Cask38
-rw-r--r--FUTURE124
-rw-r--r--LICENSE674
-rw-r--r--Makefile93
-rw-r--r--README73
-rw-r--r--README.md331
-rw-r--r--contrib/README28
-rw-r--r--contrib/dot-ctags11
-rw-r--r--debian/NEWS13
-rw-r--r--debian/changelog39
-rw-r--r--debian/compat1
-rw-r--r--debian/control46
-rw-r--r--debian/copyright120
-rw-r--r--debian/docs4
-rw-r--r--debian/elpa1
-rw-r--r--debian/elpa-test2
-rw-r--r--debian/emacsen-install30
-rw-r--r--debian/emacsen-remove8
-rw-r--r--debian/emacsen-startup21
-rw-r--r--debian/gbp.conf9
-rwxr-xr-xdebian/rules45
-rw-r--r--debian/source/format1
-rw-r--r--debian/watch3
-rw-r--r--scala-mode-auto.el87
-rw-r--r--scala-mode-constants.el204
-rw-r--r--scala-mode-feature-electric.el180
-rw-r--r--scala-mode-feature-speedbar.el89
-rw-r--r--scala-mode-feature-tags.el174
-rw-r--r--scala-mode-feature.el69
-rw-r--r--scala-mode-fontlock.el773
-rw-r--r--scala-mode-imenu.el134
-rw-r--r--scala-mode-indent.el1157
-rw-r--r--scala-mode-inf.el201
-rw-r--r--scala-mode-lib.el128
-rw-r--r--scala-mode-map.el28
-rw-r--r--scala-mode-navigation.el193
-rw-r--r--scala-mode-paragraph.el110
-rw-r--r--scala-mode-prettify-symbols.el94
-rw-r--r--scala-mode-syntax.el1047
-rw-r--r--scala-mode-ui.el159
-rw-r--r--scala-mode-variables.el55
-rw-r--r--scala-mode.el347
-rw-r--r--test/scala-mode-test.el178
-rw-r--r--test/test-helper.el1
47 files changed, 4583 insertions, 2561 deletions
diff --git a/.ert-runner b/.ert-runner
new file mode 100644
index 0000000..c07ab9f
--- /dev/null
+++ b/.ert-runner
@@ -0,0 +1 @@
+-L . \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed55a4c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.elc
+.cask
+*-pkg.el
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index ea34aa8..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,17 +0,0 @@
-In Emacs, this file should be read in -*- Outline -*- mode.
-
-Below is a list of people who have made changes or contributed to the
-scala emacs mode.
-
-* Main mode developers
-** Michel Schinz <Michel.Schinz at epfl.ch>
-** Anders Bach Nielsen <andersbach.nielsen at epfl.ch>
-
-
-* Contributions
-** Iulian Dragos <dragos at epfl.ch>
-** Stephane Micheloud <michelou at epfl.ch>
-** Victor Rodriguez <victorr at gmail.com>
-** ? <cwitty at newtonlabs.com>
-** Hemant Kumar <gethemant at gmail.com>
-** Ulrick Müller <ulm@gentoo.org>
diff --git a/Cask b/Cask
new file mode 100644
index 0000000..dc6ee8a
--- /dev/null
+++ b/Cask
@@ -0,0 +1,38 @@
+;;-*- Mode: Emacs-Lisp -*-
+;;; Cask --- project definition
+
+;; Copyright (C) 2015 Sam Halliday
+
+;; Author: Sam Halliday <Sam.Halliday@gmail.com>
+
+;;; 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
diff --git a/FUTURE b/FUTURE
deleted file mode 100644
index ea24a60..0000000
--- a/FUTURE
+++ /dev/null
@@ -1,124 +0,0 @@
--*- Outline -*-
-
-* Here is a list of future improvements to the scala mode
-
-** Automatic indentation should work in all cases
-
-
-Automatic indentation is incredibly basic and doesn't work correctly
-in many situations, including:
-
- - multi-line "case" statements, e.g.
-
- case Pair(x,y) =>
- Console.println(x);
- Console.println(y); // not indented correctly
-
- - multi-line "case" patterns, e.g.
-
- case 'a' | 'b' | 'c'
- | 'd' | 'e' | 'f' // not indented correctly
-
- - multi-line comments, e.g.
-
- /*
- * // not indented correctly
- */ // not indented correctly
-
- - other cases of single-line constructs as soon as they span
- multiple lines.
-
-** Implement customize variable to toggle smart indent on/off
-
-** Create templates for normal and scaladoc comments (with menu and shurtcut)
-
-** Scaladoc font-lock mode
-
-** Support for XEmacs
-
-** Add support for Flymode
-
-(require 'scala-mode)
-(require 'compile)
-(require 'flymake)
-(require 'font-lock)
-
-(defvar scala-build-commad nil)
-(make-variable-buffer-local 'scala-build-command)
-
-(add-hook 'scala-mode-hook
- (lambda ()
- (flymake-mode-on)
- ))
-
-(defun flymake-scala-init ()
- (let* ((text-of-first-line (buffer-substring-no-properties (point-min) (min 20 (point-max)))))
- (progn
- (remove-hook 'after-save-hook 'flymake-after-save-hook t)
- (save-buffer)
- (add-hook 'after-save-hook 'flymake-after-save-hook nil t)
- (if (string-match "^//script" text-of-first-line)
- (list "fsc" (list "-Xscript" "MainScript" "-d" "c:/tmp" buffer-file-name))
- (or scala-build-command (list "fsc" (list "-d" "c:/tmp" buffer-file-name))))
- )))
-
-(push '(".+\\.scala$" flymake-scala-init) flymake-allowed-file-name-masks)
-(push '("^\\(.*\\):\\([0-9]+\\): error: \\(.*\\)$" 1 2 nil 3) flymake-err-line-patterns)
-
-(set (make-local-variable 'indent-line-function) 'scala-indent-line)
-
-(defun scala-indent-line ()
- "Indent current line of Scala code."
- (interactive)
- (indent-line-to (max 0 (scala-calculate-indentation))))
-
-(defun scala-calculate-indentation ()
- "Return the column to which the current line should be indented."
- (save-excursion
- (scala-maybe-skip-leading-close-delim)
- (let ((pos (point)))
- (beginning-of-line)
- (if (not (search-backward-regexp "[^\n\t\r ]" 1 0))
- 0
- (progn
- (scala-maybe-skip-leading-close-delim)
- (+ (current-indentation) (* 2 (scala-count-scope-depth (point) pos))))))))
-
-(defun scala-maybe-skip-leading-close-delim ()
- (beginning-of-line)
- (forward-to-indentation 0)
- (if (looking-at "\\s)")
- (forward-char)
- (beginning-of-line)))
-
-(defun scala-face-at-point (pos)
- "Return face descriptor for char at point."
- (plist-get (text-properties-at pos) 'face))
-
-(defun scala-count-scope-depth (rstart rend)
- "Return difference between open and close scope delimeters."
- (save-excursion
- (goto-char rstart)
- (let ((open-count 0)
- (close-count 0)
- opoint)
- (while (and (< (point) rend)
- (progn (setq opoint (point))
- (re-search-forward "\\s)\\|\\s(" rend t)))
- (if (= opoint (point))
- (forward-char 1)
- (cond
-
- ;; Use font-lock-mode to ignore strings and comments
- ((scala-face-at-point (- (point) 1)))
-
- ((looking-back "\\s)")
- (incf close-count))
- ((looking-back "\\s(")
- (incf open-count))
- )))
- (- open-count close-count))))
-
-
-(provide 'scala-extensions)
-
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile b/Makefile
index 39a1484..e550ed9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,9 @@
# 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
@@ -12,41 +15,46 @@ SOURCE_DIR = $(ROOT)
##############################################################################
# Variables
+MODE_NAME = scala-mode
+
# Emacs Lisp
ELISP_COMMAND ?= emacs
-ELISP_OPTIONS += -batch -no-site-file
-ELISP_OPTIONS += -L $(ROOT)
-ELISP_OPTIONS += -f batch-byte-compile
-
-
-ELISP_FILES += scala-mode
-ELISP_FILES += scala-mode-auto
-ELISP_FILES += scala-mode-inf
-ELISP_FILES += scala-mode-indent
-ELISP_FILES += scala-mode-navigation
-ELISP_FILES += scala-mode-lib
-ELISP_FILES += scala-mode-ui
-ELISP_FILES += scala-mode-fontlock
-ELISP_FILES += scala-mode-constants
-ELISP_FILES += scala-mode-feature
-ELISP_FILES += scala-mode-feature-electric
-ELISP_FILES += scala-mode-feature-speedbar
-ELISP_FILES += scala-mode-feature-tags
-
+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
+ $(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
@@ -55,10 +63,51 @@ clean:
# Rules
.latest-build: $(ELISP_SOURCES)
- $(ELISP_COMMAND) $(ELISP_OPTIONS) $(ELISP_SOURCES)
+ $(ELISP_COMMAND) $(ELISP_OPTIONS) -f batch-byte-compile $(ELISP_SOURCES)
@$(TOUCH) $@
##############################################################################
autoloads: $(ELISP_SOURCES)
- emacs -batch -q --no-site-file --eval "(setq make-backup-files nil)" --eval "(setq generated-autoload-file (expand-file-name \"autoloads.el\"))" -f batch-update-autoloads `pwd` \ No newline at end of file
+ $(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.
diff --git a/README b/README
deleted file mode 100644
index 5d0aaac..0000000
--- a/README
+++ /dev/null
@@ -1,73 +0,0 @@
-In Emacs, this file should be read in -*- Outline -*- mode.
-
-* Introduction
-
-This directory contains the Emacs mode for Scala programs. This mode
-works only in GNU Emacs 21.1 or later. In particular, it doesn't work
-on any version of XEmacs, or any 20.x version of GNU Emacs.
-
-The mode is currently very basic, and offers:
-
-*** Basic syntax highlighting.
-*** Primitive automatic indentation.
-*** Support for interaction with the Scala interpreter.
-*** Minor mode for inserting ([{" in pairs.
- (scala-mode-electric)
-*** Tags support in Scala mode for creating, loading and completion using tags files.
- The current implementation works with exuberant ctags (http://ctags.sf.net)
- Please see the contrib/ directory for more information.
-*** Simple interaction with speedbar with support for scala files.
- Using the speedbar it is possible to get an overview of the scala
- files and using the emacs tags support, to get an overview of the
- tags in a scala file.
- For this to work please install CEDET (http://cedet.sf.net)
-*** The Scala mode has been cleaned up to work better with yasnippet from
- (http://code.google.com/p/yasnippet/). This replaces the old template stuff
- and the work on scaladoc.
-
-* Installation
-
-Put all ".el" files in a location where Emacs can find them, i.e. a
-directory appearing in the "load-path" variable.
-
- (add-to-list 'load-path "/path/to/some/directory/scala-mode")
-
-It is recommended, but not required to compile all ".el" files to
-".elc" files. This will improve load time in emacs of the scala
-mode. On Linux/UNIX simply run "make" in the scala mode directory.
-
-Add the following line to your Emacs startup file, usually "~/.emacs":
-
- (require 'scala-mode-auto)
-
-If you want to use yasnippets with the scala mode there are some things you need to do.
-First of all install yasnippets from http://code.google.com/p/yasnippet/ (the non-bundle version)
-
-Now add the following to your .emacs file to pick up the scala snippets
-
- (setq yas/my-directory "/path/to/some/directory/scala-mode/contrib/yasnippet/snippets")
- (yas/load-directory yas/my-directory)
-
-And then add this to your .emacs file
-
- (add-hook 'scala-mode-hook
- '(lambda ()
- (yas/minor-mode-on)
- ))
-
-Restart Emacs or evaluate the above line.
-
-From that point on, loading a file whose name ends in ".scala"
-automatically turns Scala mode on. It can also be turned on manually
-using the "scala-mode" command.
-
-The get the best expirience from using the scala mode in emacs, please
-visit the costumization options for the scala mode.
-
-
-* Future plans
-
-See FUTURE file for a list of future enhancements to the scala emacs
-mode. If there is something missing, please post comment on
-scala-tools@listes.epfl.ch.
-
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cc76f26
--- /dev/null
+++ b/README.md
@@ -0,0 +1,331 @@
+# 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)
diff --git a/contrib/README b/contrib/README
deleted file mode 100644
index 03818f2..0000000
--- a/contrib/README
+++ /dev/null
@@ -1,28 +0,0 @@
-In Emacs, this file should be read in -*- Outline -*- mode.
-
-* Contribution
-
-** Exuberant Ctags
-
-To let ctags know how to parse scala files, put the content of
-dot-ctags into your $HOME/.ctags file. This will parse scala files and
-give the following kinds.
-
-Scala
- c classes
- o objects
- t traits
- m case-classes
- a abstract-classes
- f functions
- V values
- v variables
- T types
-
-The default in the scala mode is to parse scala files for all the
-above kinds to produce tags. This can give a rather huge amount of
-tags in speedbar for a scala file. This can be reduced by adding
-
---Scala-kinds=[+|-]kinds
-
-where kinds are the one letter abbrevs above.
diff --git a/contrib/dot-ctags b/contrib/dot-ctags
deleted file mode 100644
index 09f68ff..0000000
--- a/contrib/dot-ctags
+++ /dev/null
@@ -1,11 +0,0 @@
---langdef=Scala
---langmap=Scala:.scala
---regex-Scala=/^[^\*\/]*class[ \t]*([a-zA-Z0-9_]+)/\1/c,classes/
---regex-Scala=/^[^\*\/]*object[ \t]*([a-zA-Z0-9_]+)/\1/o,objects/
---regex-scala=/^[^\*\/]*trait[ \t]*([a-zA-Z0-9_]+)/\1/t,traits/
---regex-Scala=/^[^\*\/]*case[ \t]*class[ \t]*([a-zA-Z0-9_]+)/\1/m,case-classes/
---regex-Scala=/^[^\*\/]*abstract[ \t]*class[ \t]*([a-zA-Z0-9_]+)/\1/a,abstract-classes/
---regex-Scala=/^[^\*\/]*def[ \t]*([a-zA-Z0-9_]+)[ \t]*.*[:=]/\1/f,functions/
---regex-Scala=/^[^\*\/]*val[ \t]*([a-zA-Z0-9_]+)[ \t]*[:=]/\1/V,values/
---regex-Scala=/^[^\*\/]*var[ \t]*([a-zA-Z0-9_]+)[ \t]*[:=]/\1/v,variables/
---regex-Scala=/^[^\*\/]*type[ \t]*([a-zA-Z0-9_]+)[ \t]*[\[<>=]/\1/T,types/
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644
index 0000000..3430ca9
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,13 @@
+scala-mode-el (1:1.1.0-1) unstable; urgency=medium
+ Replaced old version of scala-mode that isn't available in Melpa anymore with
+ newer version which replaced the old in Melpa(once was named scala-mode2,
+ now it's scala-mode) and is actively maintained.
+
+ This new scala-mode is more tested and reliable, however, it lacks the feature
+ of executing scala expressions in scala REPL process. For that and many other
+ IDE like features(complex refactor options, type/class hierarchy, code
+ navigation, etc.) emacs users are encouraged to install lsp-mode(or eglot)
+ which works in conjunction with this mode and has support for scala Metals
+ language server.
+
+ -- Sławomir Wójcik <valdaer@gmail.com> Fri, 12 Jun 2020 01:19:59 +0200
diff --git a/debian/changelog b/debian/changelog
index 4a453ce..b410a4e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,42 @@
+scala-mode-el (1:1.1.0-1) unstable; urgency=medium
+
+ [ Sławomir Wójcik ]
+ * Adopt package; this package is now maintained by the Debian Emacsen team.
+ (Closes: #766441)
+ * control: updated maintainer/uploaders, long description and dependencies
+ * Updated rules to use dh_elpa, added necessary elpa and elpa-test files
+ * Added watch file
+ * Updated docs file
+ * Added source format
+ * Added NEWS file
+ * Removed emacsen-install, emacsen-remove and emacsen-startup files which
+ were no longer necessary due to migration to dh_elpa
+
+ [ Sławomir Wójcik and Nicholas D Steeves]
+ * New upstream version 1.1.0.
+ * Migrate to debhelper-compat 13.
+ * Update copyright file to reflect new upstream source, and migrate to a
+ machine-readable copyright file.
+ * Add gbp.conf.
+ * Introduce elpa-scala-mode; scala-mode-el is now a dummy transitional
+ package.
+ * Set Vcs URLs to new Debian Emacsen Team location.
+ * Declare Standards-Version 4.5.1.
+
+ [ Nicholas D Steeves ]
+ * Add Breaks, Replaces, and Provides to elpa-scala-mode to ensure smooth
+ upgrades.
+ * Add epoch to version, so that apt will upgrade existing users from
+ 20111005-2.1 to 1.1.0-1.
+ * Declare Rules-Requires-Root: no.
+ * Declare dummy transitional package scala-mode-el as Section: oldlibs so
+ that deborphan will suggest its removal.
+ * elpa-test: Fix autopkgtests by setting autopkgtest_keep, thus retaining
+ the files that contain scala-mode's tests.
+ * Add myself to Uploaders.
+
+ -- Nicholas D Steeves <nsteeves@gmail.com> Sun, 06 Dec 2020 15:57:01 -0500
+
scala-mode-el (20111005-2.1) unstable; urgency=medium
* Non-maintainer upload.
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 7f8f011..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
diff --git a/debian/control b/debian/control
index dfd93a0..7c0f937 100644
--- a/debian/control
+++ b/debian/control
@@ -1,19 +1,37 @@
Source: scala-mode-el
Section: editors
-Priority: extra
-Maintainer: Mike O'Connor <stew@debian.org>
-Build-Depends: debhelper (>= 7.0.50~)
-Build-Depends-Indep: emacs
-Standards-Version: 3.9.2
-Vcs-Browser: http://git.vireo.org/scala-mode-el.git
-Vcs-Git: git://git.vireo.org/scala-mode-el.git
-Homepage: http://www.scala-lang.org
+Priority: optional
+Maintainer: Debian Emacsen team <debian-emacsen@lists.debian.org>
+Uploaders: Sławomir Wójcik <valdaer@gmail.com>,
+ Nicholas D Steeves <nsteeves@gmail.com>
+Build-Depends: debhelper-compat (= 13),
+ dh-elpa
+Rules-Requires-Root: no
+Standards-Version: 4.5.1
+Vcs-Browser: https://salsa.debian.org/emacsen-team/scala-mode-el
+Vcs-Git: https://salsa.debian.org/emacsen-team/scala-mode-el.git
+Homepage: https://github.com/hvesalai/emacs-scala-mode
+Testsuite: autopkgtest-pkg-elpa
-Package: scala-mode-el
+Package: elpa-scala-mode
Architecture: all
-Depends: ${misc:Depends}, emacs23 | emacsen
+Depends: ${elpa:Depends},
+ ${misc:Depends}
+Recommends: emacs (>= 46.0)
+Enhances: emacs
+Breaks: scala-mode-el (<< 1:1.1.0-1~)
+Replaces: scala-mode-el (<< 1:1.1.0-1~)
+Provides: scala-mode-el
Description: Emacs major mode for editing scala source code
- scala-mode provides syntax highlighting and indentation for scala
- source code inside emacs. Included is the ability to interact with a
- scala interpreter inside emacs and to send expressions from scala
- source files to the running interpreter.
+ scala-mode provides syntax highlighting, indentation, comments/multi-line
+ strings, motion commands for scala source code inside emacs. IDE like features
+ are in lsp-mode which works in conjunction with this mode and has support for
+ scala Metals language server.
+
+Package: scala-mode-el
+Section: oldlibs
+Architecture: all
+Depends: ${misc:Depends},
+ elpa-scala-mode
+Description: transitional dummy package, scala-mode-el to elpa-scala-mode
+ This dummy package may be safely removed.
diff --git a/debian/copyright b/debian/copyright
index 52e3758..2e2a9de 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,58 +1,76 @@
-Initially packaged by Mike O'Connor <stew@debian.org> on October 5, 2011
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: emacs-scala-mode
+Source: https://github.com/hvesalai/emacs-scala-mode
-The software was obtained via svn checkout from:
-http://lampsvn.epfl.ch/svn-repos/scala/scala-tool-support/trunk/src/emacs
+Files: *
+Copyright: (C) 2012 Heikki Vesalainen
+License: GPL-3+
-See
-http://www.scala-lang.org/node/354
+Files: Cask
+Copyright: 2015 Sam Halliday
+License: GPL-3+
-Authors:
-Michel Schinz <Michel.Schinz at epfl.ch>
-Anders Bach Nielsen <andersbach.nielsen at epfl.ch>
-Iulian Dragos <dragos at epfl.ch>
-Stephane Micheloud <michelou at epfl.ch>
-Victor Rodriguez <victorr at gmail.com>
-? <cwitty at newtonlabs.com>
-Hemant Kumar <gethemant at gmail.com>
-Ulrick Müller <ulm@gentoo.org>
+Files: scala-mode-prettify-symbols.el
+Copyright: (C) 2016 Merlin Göttlinger
+License: GPL-3+
-Copyright:
-Copyright (C) 2009-2011 Scala Dev Team at EPFL
-Copyright (c) 2002-2011 EPFL, Lausanne
+Files: Makefile
+Copyright: (C) 2002-2011 EPFL, Lausanne, unless otherwise specified.
+License: SCALA-LICENSE
-License:
+Files: debian/*
+Copyright: (C) 2012 Mike O'Connor <stew@debian.org>
+ (C) 2020 Sławomir Wójcik <valdaer@gmail.com>
+License: GPL-3+
-;; 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.
+License: GPL-3+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in `/usr/share/common-licenses/GPL-3'
+License: 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.
diff --git a/debian/docs b/debian/docs
index a4f04e5..b43bf86 100644
--- a/debian/docs
+++ b/debian/docs
@@ -1,3 +1 @@
-README
-FUTURE
-contrib \ No newline at end of file
+README.md
diff --git a/debian/elpa b/debian/elpa
new file mode 100644
index 0000000..abf136d
--- /dev/null
+++ b/debian/elpa
@@ -0,0 +1 @@
+*.el
diff --git a/debian/elpa-test b/debian/elpa-test
new file mode 100644
index 0000000..b4a1e32
--- /dev/null
+++ b/debian/elpa-test
@@ -0,0 +1,2 @@
+ert_eval = (load-file "test/test-helper.el")
+autopkgtest_keep = test/*
diff --git a/debian/emacsen-install b/debian/emacsen-install
deleted file mode 100644
index 87e574f..0000000
--- a/debian/emacsen-install
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh -e
-
-FLAVOR=$1
-if [ ${FLAVOR} = emacs ]; then exit 0; fi
-if [ ${FLAVOR%${FLAVOR#?}} = 'x' ]; then echo "ignoring unsupported flavor: $FLAVOR" ; exit 0 ; fi
-
-PACKAGE=scala-mode
-echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR}
-
-# The byte-compiled files goes into the site-lisp directory.
-BCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE}
-install -m 755 -d ${BCDIR}
-
-# The elisp source files are in the generic site-list directory.
-SRCDIR=/usr/share/emacs/site-lisp/${PACKAGE}
-SRC=`find ${SRCDIR} -name '*.el' -exec basename '{}' ';'`
-
-# Prepare for byte-compiling the source files.
-cd ${BCDIR}
-ln -sf ${SRCDIR}/*.el .
-cat << EOF > path.el
-(setq load-path (cons "." load-path) byte-compile-warnings nil)
-EOF
-
-# Byte-compile elisp files.
-FLAGS="--no-site-file --no-init-file --batch -l path.el -f batch-byte-compile"
-${FLAVOR} ${FLAGS} ${SRC}
-rm -f path.el
-
-exit 0
diff --git a/debian/emacsen-remove b/debian/emacsen-remove
deleted file mode 100644
index 401f332..0000000
--- a/debian/emacsen-remove
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh -e
-FLAVOR=$1
-PACKAGE=scala-mode
-if [ ${FLAVOR} != emacs ]; then
- echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR}
- rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE}
-fi
-exit 0
diff --git a/debian/emacsen-startup b/debian/emacsen-startup
deleted file mode 100644
index c57f2e8..0000000
--- a/debian/emacsen-startup
+++ /dev/null
@@ -1,21 +0,0 @@
-;; -*-emacs-lisp-*-
-
-(if (not (file-exists-p "/usr/share/emacs/site-lisp/scala-mode"))
- (message "Package scala-mode-el removed but not purged. Skipping setup.")
-
- (let ((instdir (concat "/usr/share/"
- (symbol-name debian-emacs-flavor)
- "/site-lisp/scala-mode")))
-
- ;; Only load scala-mode if it has been installed.
- (if (zerop (length (file-expand-wildcards instdir)))
- (message "scala-mode not for this flavor. Skipping.")
-
- ;; The sml-mode package follows the Debian/GNU Linux 'emacsen' policy and
- ;; byte-compiles its elisp files for each 'emacs flavor'. The compiled
- ;; code is then installed in a subdirectory of the respective site-lisp
- ;; directory.
- (debian-pkg-add-load-path-item instdir)
-
- ;; Autoload sml-mode top-level functions site-wide.
- (load "scala-mode-auto"))))
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..d7d8bf2
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,9 @@
+[DEFAULT]
+upstream-branch = upstream
+debian-branch = master
+upstream-tag = v%(version)s
+debian-tag = debian/%(version)s
+
+sign-tags = True
+pristine-tar = False
+pristine-tar-commit = False
diff --git a/debian/rules b/debian/rules
index 47ae75c..e8e22ba 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,45 +1,4 @@
#!/usr/bin/make -f
-PACKAGE=scala-mode-el
-
-clean:
- dh_testdir
- dh_testroot
- rm -f build-stamp
- $(MAKE) clean
- dh_clean
-
-build: build-arch build-indep
-build-arch: build-stamp
-build-indep: build-stamp
-
-build-stamp:
- dh_testdir
- $(MAKE) autoloads
- touch $@
-
-install: build
- dh_testdir
- dh_testroot
- dh_prep
- dh_installdirs usr/share/emacs/site-lisp/scala-mode
- cp *el debian/scala-mode-el/usr/share/emacs/site-lisp/scala-mode
-
-binary-indep: install
- dh_testdir
- dh_testroot
- dh_installchangelogs
- dh_installdocs
- dh_installemacsen
- dh_compress
- dh_fixperms
- dh_installdeb
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-binary-arch: build install
-
-binary: binary-indep binary-arch
-
-.PHONY: build clean binary-indep binary-arch binary install
+%:
+ dh $@ --with elpa
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..6b129f9
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,3 @@
+version=4
+opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/emacs-scala-mode-$1\.tar\.gz/ \
+ https://github.com/hvesalai/emacs-scala-mode/tags .*/v?(\d\S+)\.tar\.gz
diff --git a/scala-mode-auto.el b/scala-mode-auto.el
deleted file mode 100644
index 3b45785..0000000
--- a/scala-mode-auto.el
+++ /dev/null
@@ -1,87 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-auto.el - Autoloads file for the scala mode
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; We now depend on font-locking features only in emacs 21.x and newer
-(unless (<= 21 emacs-major-version)
- (error
- (format "The Scala mode require Emacs version 21.x (and not your Emacs version %s.%s)" emacs-major-version emacs-minor-version)))
-
-;; TODO insert check for correct version of speedbar
-
-
-;; Attach .scala files to the scala-mode
-(add-to-list 'auto-mode-alist '("\\.scala\\'" . scala-mode))
-(modify-coding-system-alist 'file "\\.scala$" 'utf-8)
-
-
-;; Autoload from scala-mode.el
-(autoload (quote scala-mode) "scala-mode" "\
-Major mode for editing Scala code.
-
-When started, run `scala-mode-hook'.
-
-\\{scala-mode-map}" t nil)
-
-
-;; Autoload from scala-mode-inf.el
-(autoload (quote scala-interpreter-running-p-1) "scala-mode-inf" nil t nil)
-
-(autoload (quote scala-run-scala) "scala-mode-inf" "Run a Scala interpreter in an Emacs buffer" t nil)
-
-(autoload (quote scala-switch-to-interpreter) "scala-mode-inf" "Switch to buffer containing the interpreter" t nil)
-
-(autoload (quote scala-eval-region) "scala-mode-inf" "Send current region to Scala interpreter." t nil)
-
-(autoload (quote scala-eval-buffer) "scala-mode-inf" "Send whole buffer to Scala interpreter." t nil)
-
-(autoload (quote scala-load-file) "scala-mode-inf" "Load a file in the Scala interpreter." t nil)
-
-(autoload (quote scala-quit-interpreter) "scala-mode-inf" "Quit Scala interpreter." t nil)
-
-
-(provide 'scala-mode-auto)
diff --git a/scala-mode-constants.el b/scala-mode-constants.el
deleted file mode 100644
index a98380b..0000000
--- a/scala-mode-constants.el
+++ /dev/null
@@ -1,204 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-constants.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-constants)
-
-(require 'cl)
-(require 'regexp-opt)
-
-;; Helper functions
-
-(defun scala-regexp-opt-charset (chars)
- ;;
- ;; Return a regexp to match a character in CHARS.
- ;;
- ;; The basic idea is to find character ranges. Also we take care in the
- ;; position of character set meta characters in the character set regexp.
- ;;
- (let* ((charmap (make-char-table 'case-table))
- (start -1) (end -2)
- (charset "")
- (bracket "") (dash "") (caret ""))
- ;;
- ;; Make a character map but extract character set meta characters.
- (dolist (char chars)
- (case char
- (?\]
- (setq bracket "]"))
- (?^
- (setq caret "^"))
- (?-
- (setq dash "-"))
- (otherwise
- (aset charmap char t))))
- ;;
- ;; Make a character set from the map using ranges where applicable.
- (map-char-table
- (lambda (c v)
- (when v
- (if (listp c) (setq start (car c) end (cdr c))
- (if (= (1- c) end) (setq end c)
- (if (> end (+ start 2))
- (setq charset (format "%s%c-%c" charset start end))
- (while (>= end start)
- (setq charset (format "%s%c" charset start))
- (incf start)))
- (setq start c end c)))))
- charmap)
- (when (>= end start)
- (if (> end (+ start 2))
- (setq charset (format "%s%c-%c" charset start end))
- (while (>= end start)
- (setq charset (format "%s%c" charset start))
- (incf start))))
- ;;
- ;; Make sure a caret is not first and a dash is first or last.
- (if (and (string-equal charset "") (string-equal bracket ""))
- (concat "[" dash caret "]")
- (concat "[" bracket charset caret dash "]"))))
-
-
-;; Constants
-
-
-(defconst scala-number-re
- "[[:digit:]]+\\(\\.[[:digit:]]+\\)?\\([eE][+-]?[[:digit:]]+\\)?[fl]?"
- "Regular expression matching a Scala number (integer or float).")
-
-(defconst scala-rawstring-re
- "\"\"\"[^\"\"\"]*\"\"\""
- "Regular expression matching a Scala raw string literal.")
-
-(defconst scala-string-re
- "\"\\([^\"\\\\]\\|\\\\\.\\)*\""
- "Regular expression matching a Scala string literal.")
-
-(defconst scala-char-re
- "'\\([^\\\\]\\|\\(\\\\[^']\\)\\)'"
- "Regular expression matching a Scala character literal.")
-
-(defconst scala-literal-re
- (concat "\\(" "\\(" scala-number-re "\\)"
- "\\|" "\\(" scala-rawstring-re "\\)"
- "\\|" "\\(" scala-string-re "\\)"
- "\\|" "\\(" scala-char-re "\\)" "\\)")
- "Regular expression matching any Scala literal.")
-
-(defconst scala-most-special-chars (mapcar 'identity "<>+-*/|@#%&!?$^`~")
- "List of almost all Scala special characters.
-Not included in this list are the special characters which are
-reserved keywords when used alone.")
-
-(defconst scala-all-special-chars (append (mapcar 'identity ":;,=")
- scala-most-special-chars)
- "List of all Scala special characters.")
-
-(defconst scala-most-special-char-re
- (scala-regexp-opt-charset scala-most-special-chars)
- "Regular expression matching a single Scala special character")
-
-(defconst scala-all-special-char-re
- (scala-regexp-opt-charset scala-all-special-chars)
- "Regular expression matching a single Scala special character")
-
-(defconst scala-keywords-re
- (regexp-opt '("abstract" "case" "class" "catch" "def" "do" "else" "extends"
- "final" "finally" "for" "forSome" "if" "implicit" "import" "lazy"
- "new" "match" "mixin" "object" "override" "package" "private"
- "protected" "requires" "return" "sealed" "super" "this" "throw"
- "trait" "try" "type" "val" "var" "with" "while" "yield")
- 'words))
-
-(defconst scala-constants-re
- (regexp-opt '("true" "false" "null") 'words))
-
-(defconst scala-special-ident-re
- (concat "\\(" scala-all-special-char-re "\\{2,\\}"
- "\\|" scala-most-special-char-re "+"
- "\\)"))
-
-(defconst scala-ident-re
- (let* ((varid-re "[[:alnum:]]+")
- (id-re (concat "\\(" varid-re "\\|" scala-special-ident-re "\\)")))
- (concat id-re
- "\\(" "_+" "\\(" id-re "\\)?" "\\)*"))
- "Regular expression matching a Scala identifier.")
-
-(defconst scala-var-ident-re
- (concat "[[:lower:]][[:alnum:]]*" "\\(_" scala-ident-re "\\)*")
- "Relgular expression matching a Scala 'variable' identifier.")
-
-(defconst scala-qual-ident-re
- (concat scala-ident-re "\\(" "\\." scala-ident-re "\\)*"))
-
-(defconst scala-capitalized-ident-re
- (concat "\\(\\)\\([[:upper:]]" scala-ident-re "\\)"))
-
-(defconst scala-expr-start-re
- (concat
- (regexp-opt '("if" "else" "for" "do" "yield") 'words) "\\|"
- (regexp-opt '("=" "=>") t)))
-
-(defconst scala-expr-starter
- (mapcar (lambda (pair) (cons (car pair) (concat "\\<" (cdr pair) "\\>")))
- '(("else" . "if")
- ("yield" . "for")
- ("do" . "for")
- ("extends" . "class")
- ("with" . "class")
- ("=>" . "case"))))
-
-(defconst scala-expr-middle-re
- (regexp-opt (mapcar #'car scala-expr-starter) 'words))
-
-(defconst scala-compound-expr-re
- "\\<else\\s +if\\>")
-
-(defconst scala-comment-begin-or-end-re
- (concat "\\(" "^/\\*.*" "\\|" "^//.*" "\\|" ".*\\*/$" "\\)"))
-
diff --git a/scala-mode-feature-electric.el b/scala-mode-feature-electric.el
deleted file mode 100644
index 09182b6..0000000
--- a/scala-mode-feature-electric.el
+++ /dev/null
@@ -1,180 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-feature-electric.el - electric editing commands for scala files
-
-;; Copyright (C) 2009 by Hemant Kumar (gethemant at gmail to com)
-;; Modified by Anders Bach Nielsen <andersbach.nielsen at epfl dot ch> to fit into the scala mode
-;; Based on ruby-electric by Dee Zsombor <dee dot zsombor at gmail dot com>.
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-feature-electric)
-
-;; Customization
-
-(defgroup scala-mode-feature:electric nil
- "Minor mode providing electric editing commands for scala files"
- :group 'scala)
-
-
-(defcustom scala-mode-feature:electric-expand-delimiters-list '(all)
- "*List of contexts where matching delimiter should be
-inserted. The word 'all' will do all insertions."
- :type '(set :extra-offset 8
- (const :tag "Everything" all )
- (const :tag "Curly brace" ?\{ )
- (const :tag "Square brace" ?\[ )
- (const :tag "Round brace" ?\( )
- (const :tag "Quote" ?\' )
- (const :tag "Double quote" ?\" )
- (const :tag "Back quote" ?\` )
- (const :tag "Vertical bar" ?\| ))
- :group 'scala-mode-feature:electric)
-
-
-(defcustom scala-mode-feature:electric-newline-before-closing-bracket nil
- "*Controls whether a newline should be inserted before the
-closing bracket or not."
- :type 'boolean
- :group 'scala-mode-feature:electric)
-
-
-(defcustom scala-mode-feature:electric-on-per-default nil
- "*Controls whether scala electric mode should be on per default or not."
- :type 'boolean
- :group 'scala-mode-feature:electric)
-
-;; Variables
-
-(defvar scala-mode-feature-electric-matching-delimeter-alist
- '((?\[ . ?\])
- (?\( . ?\))
- (?\' . ?\')
- (?\` . ?\`)
- (?\" . ?\")))
-
-
-(defvar scala-mode-feature-electric-mode scala-mode-feature:electric-on-per-default
- "nil disables scala electric mode, non-nil enables.")
-
-(defvar scala-mode-feature-electric-mode-map (make-sparse-keymap)
- "Keymap for scala electric minor mode.")
-
-;;; Mode setup
-
-(make-variable-buffer-local 'scala-mode-feature-electric-mode)
-
-(defun scala-mode-feature-electric-mode (&optional arg)
- ""
- (interactive "P")
- (setq scala-mode-feature-electric-mode
- (if (null arg)
- ;; Toggle mode
- (not scala-mode-feature-electric-mode)
- ;; Enable/Disable according to arg
- (> (prefix-numeric-value arg) 0)))
- )
-
-;; Alias for some backwards compat
-(defalias 'scala-electric-mode 'scala-mode-feature-electric-mode)
-
-
-;; Functions
-(defun scala-mode-feature-electric-active-p ()
- scala-mode-feature-electric-mode)
-
-(defun scala-mode-feature-electric-code-at-point-p()
- (and scala-mode-feature-electric-mode
- (let* ((properties (text-properties-at (point))))
- (and (null (memq 'font-lock-string-face properties))
- (null (memq 'font-lock-comment-face properties))))))
-
-(defun scala-mode-feature-electric-string-at-point-p()
- (and scala-mode-feature-electric-mode
- (consp (memq 'font-lock-string-face (text-properties-at (point))))))
-
-(defun scala-mode-feature-electric-is-last-command-char-expandable-punct-p()
- (or (memq 'all scala-mode-feature:electric-expand-delimiters-list)
- (memq last-command-char scala-mode-feature:electric-expand-delimiters-list)))
-
-(defun scala-mode-feature-electric-curlies(arg)
- (interactive "P")
- (self-insert-command (prefix-numeric-value arg))
- (if (scala-mode-feature-electric-is-last-command-char-expandable-punct-p)
- (cond ((scala-mode-feature-electric-code-at-point-p)
- (insert " ")
- (save-excursion
- (if scala-mode-feature:electric-newline-before-closing-bracket
- (newline))
- (insert "}")))
- ((scala-mode-feature-electric-string-at-point-p)
- (save-excursion
- (backward-char 1)
- (when (char-equal ?\# (preceding-char))
- (forward-char 1)
- (insert "}")))))))
-
-(defun scala-mode-feature-electric-matching-char(arg)
- (interactive "P")
- (self-insert-command (prefix-numeric-value arg))
- (and (scala-mode-feature-electric-is-last-command-char-expandable-punct-p)
- (scala-mode-feature-electric-code-at-point-p)
- (save-excursion
- (insert (cdr (assoc last-command-char
- scala-mode-feature-electric-matching-delimeter-alist))))))
-
-(defun scala-mode-feature-electric-install ()
- (or (assoc 'scala-mode-feature-electric-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(scala-mode-feature-electric-mode " electric") minor-mode-alist)))
-
- (or (assoc 'scala-mode-feature-electric-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'scala-mode-feature-electric-mode scala-mode-feature-electric-mode-map)
- minor-mode-map-alist)))
-
- (define-key scala-mode-feature-electric-mode-map "{" 'scala-mode-feature-electric-curlies)
- (define-key scala-mode-feature-electric-mode-map "(" 'scala-mode-feature-electric-matching-char)
- (define-key scala-mode-feature-electric-mode-map "[" 'scala-mode-feature-electric-matching-char)
- (define-key scala-mode-feature-electric-mode-map "\"" 'scala-mode-feature-electric-matching-char)
-
- t)
diff --git a/scala-mode-feature-speedbar.el b/scala-mode-feature-speedbar.el
deleted file mode 100644
index 94d05ac..0000000
--- a/scala-mode-feature-speedbar.el
+++ /dev/null
@@ -1,89 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-feature-speedbar.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-feature-speedbar)
-
-(eval-when-compile
- (require 'scala-mode-feature-tags))
-
-(require 'speedbar)
-
-;; Customization
-
-(defgroup scala-mode-feature:speedbar nil
- "Options how the speedbar works under Scala mode"
- :group 'scala)
-
-
-(defcustom scala-mode-feature:speedbar-open nil
- "Normally scala-mode starts with the speedbar closed.\
-Turning this on will open it whenever scala-mode is loaded."
- :type 'boolean
- :set (lambda (sym val)
- (set-default sym val)
- (when val
- (speedbar 1)))
- :group 'scala-mode-feature:speedbar)
-
-
-(defun scala-mode-feature-speedbar-install ()
- (define-key speedbar-file-key-map "\C-t" '(lambda () (interactive)
- (speedbar-flush-expand-line)))
-
- (add-hook 'speedbar-mode-hook
- (lambda()
- (speedbar-add-supported-extension "\\.scala")))
-
- (setq speedbar-fetch-etags-command scala-mode-feature:tags-command)
-
- (setq speedbar-fetch-etags-arguments '("-e" "-f -"))
-
- (add-to-list 'speedbar-fetch-etags-parse-list
- '("\\.scala" . speedbar-parse-c-or-c++tag))
-
- t)
diff --git a/scala-mode-feature-tags.el b/scala-mode-feature-tags.el
deleted file mode 100644
index 9ccfbf1..0000000
--- a/scala-mode-feature-tags.el
+++ /dev/null
@@ -1,174 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-feature-tags.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-feature-tags)
-
-(require 'etags)
-
-(defgroup scala-mode-feature:tags nil
- "Creating and using TAGS file searches"
- :group 'scala)
-
-
-(defcustom scala-mode-feature:tags-command "ctags"
- "Tags command for parsing scala code.
-Please see the contrib directory for ctags options for parsing scala files."
- :type 'string
- :group 'scala-mode-feature:tags)
-
-
-(defcustom scala-mode-feature:tags-option "-e -o %s -R %s"
- "Options for the ctags command"
- :type 'string
- :group 'scala-mode-feature:tags)
-
-
-(defcustom scala-mode-feature:tags-ask-when-reload nil
- "Indicates whether the user should confirm reload a TAGS table or not."
- :type 'boolean
- :group 'scala-mode-feature:tags)
-
-(defvar scala-mode-feature-tags-completion-table nil
- "")
-
-(defvar scala-mode-feature-tags-tag-file nil
- "")
-
-(defun scala-mode-feature-tags-create (dir-name)
- "Create TAGS file"
- (interactive "DTAGS file directory: ")
- (message "Creating TAGS, please wait...")
- (let*
- ((tags-file-name (concat dir-name "/TAGS"))
- (args (format scala-mode-feature:tags-option tags-file-name dir-name)))
- (shell-command
- (concat scala-mode-feature:tags-command " " args))
- (flet ((yes-or-no-p (p) (if scala-mode-feature:tags-ask-when-reload
- (y-or-n-p p)
- t)))
- (visit-tags-table tags-file-name))
- (setq scala-mode-feature-tags-tag-file tags-file-name)))
-
-
-(defun scala-mode-feature-tags-load (file-name)
- "Load TAGS file"
- (interactive "fTAGS file: ")
- (if (and (file-exists-p file-name) (file-readable-p file-name))
- (progn
- (visit-tags-table file-name)
- (setq scala-mode-feature-tags-tag-file file-name))
- (message "The TAGS file does not exist!")))
-
-
-(defun scala-mode-feature-tags-complete ()
- "Perform completion on the text around point.
-Completes to the set of names listed in the current tags table.
-The string to complete is chosen in the same way as the default
-for \\[find-tag] (which see)."
- (interactive)
- (let ((pattern (scala-mode-feature-tags-get-pattern))
- beg
- completion
- (scala-comp scala-mode-feature-tags-completion-table))
- (if (not pattern) (message "Nothing to complete")
- (search-backward pattern)
- (setq beg (point))
- (forward-char (length pattern))
- (setq completion (try-completion pattern scala-comp nil))
- (cond
- ((eq completion t))
- ((null completion)
- (message "Can't find completion for \"%s\"" pattern)
- (ding))
- ((not (string= pattern completion))
- (delete-region beg (point))
- (insert completion))
- (t
- (message "Making completion list...")
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list
- (all-completions pattern scala-comp)))
- (message "Making completion list...%s" "done"))))))
-
-
-(defun scala-mode-feature-tags-completion-table ()
- (or (and scala-mode-feature-tags-tag-file
- scala-mode-feature-tags-completion-table)
- (let ((tags-table
- (if (and scala-mode-feature-tags-tag-file
- (functionp 'etags-tags-completion-table))
- (with-current-buffer (get-file-buffer scala-mode-feature-tags-tag-file)
- (etags-tags-completion-table))
- nil)))
- (unless tags-table
- (error "No TAGS file active!"))
- (setq scala-mode-feature-tags-completion-table tags-table))))
-
-
-(defun scala-mode-feature-tags-get-pattern ()
- (save-excursion
- (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (if (or (re-search-backward "\\sw\\|\\s_"
- (save-excursion (beginning-of-line) (point))
- t)
- (re-search-forward "\\(\\sw\\|\\s_\\)+"
- (save-excursion (end-of-line) (point))
- t))
- (progn (goto-char (match-end 0))
- (buffer-substring-no-properties
- (point)
- (progn (forward-sexp -1)
- (while (looking-at "\\s'")
- (forward-char 1))
- (point))))
- nil)))
-
-(defun scala-mode-feature-tags-install ()
-
- t)
diff --git a/scala-mode-feature.el b/scala-mode-feature.el
deleted file mode 100644
index 825a7dc..0000000
--- a/scala-mode-feature.el
+++ /dev/null
@@ -1,69 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-feature.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-feature)
-
-;; Feature loading
-
-(defvar scala-mode-feature-list
- '(scala-mode-feature-tags
- scala-mode-feature-speedbar
- scala-mode-feature-electric
- )
- "List of features")
-
-(defvar scala-mode-feature-installed-p nil)
-
-(defun scala-mode-feature-install ()
- (unless scala-mode-feature-installed-p
- (dolist (feature scala-mode-feature-list)
- (when (require feature nil t)
- (apply
- (intern (concat (symbol-name feature) "-install"))
- (list))))
- (setq scala-mode-feature-installed-p t)))
diff --git a/scala-mode-fontlock.el b/scala-mode-fontlock.el
index 508ce57..7617259 100644
--- a/scala-mode-fontlock.el
+++ b/scala-mode-fontlock.el
@@ -1,209 +1,584 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-fontlock.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; 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
-(provide 'scala-mode-fontlock)
+(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))
-(require 'cl)
-(require 'font-lock)
-(require 'scala-mode-constants)
-(require 'scala-mode-lib)
-(require 'scala-mode-navigation)
-
-
-(defun scala-mark-borders (funs)
- (loop for (fun . flag) in funs
- if flag collect (point-marker)
- while (funcall fun)
- if flag collect (point-marker)))
-
-(defun scala-make-match (funs)
- (let ((start-mark (point-marker))
- (markers (scala-mark-borders funs))
- (end-mark (point-marker)))
- (cons start-mark (cons end-mark markers))))
-
-(defconst scala-binding-end-re
- (regexp-opt '(":" "=" "=>" ";" "<-")))
-
-(defun scala-match-and-skip-binding (limit)
- (skip-chars-forward " ()")
- (and (not (or (looking-at "\\<\\(extends\\|with\\)\\>\\|{")
- (scala-looking-at-special-identifier scala-binding-end-re)))
- (ignore-errors
- (save-restriction
- (narrow-to-region (point-min) limit)
- (let ((matches (scala-make-match
- '((scala-forward-ident . t)
- ((lambda ()
- (scala-forward-spaces)
- (when (scala-looking-at-special-identifier ":")
- (forward-char)
- (scala-forward-spaces)
- t)) . nil)
- ((lambda ()
- (scala-forward-type)
- (scala-when-looking-at "\\s *\\*")
- t) . t)))))
- (scala-when-looking-at "\\s *,")
- (set-match-data matches)))
- t)))
-
-(defun scala-match-and-skip-ident (limit)
- (scala-forward-spaces)
- (when (and (not (looking-at scala-keywords-re))
- (looking-at scala-qual-ident-re))
+ (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 "\\<forSome\\>"))
+; (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))
- t))
-
-(defun scala-match-and-skip-type-param (limit)
- (scala-when-looking-at "\\s *[[,]\\s *"
- (let ((matches (scala-make-match '((scala-forward-type-param . t)))))
- (scala-when-looking-at "\\s *\\]")
- (set-match-data matches)
- t)))
-
-(defun scala-match-and-skip-result-type (limit)
- (scala-when-looking-at "\\s *:\\s *"
- (set-match-data (list (point-marker)
- (progn (scala-forward-type) (point-marker))))
- t))
-
-(defconst scala-pattern-end-re
- (regexp-opt '("if" "case" "class") 'words))
-
-(defconst scala-pattern-end-special-re
- (regexp-opt '( "=>" "=" "<-") t))
-
-(defun scala-match-and-skip-pattern (limit)
- (while (progn
- (skip-chars-forward "()[], ")
- (and (not (or (looking-at scala-pattern-end-re)
- (scala-looking-at-special-identifier
- scala-pattern-end-special-re)))
- (looking-at scala-literal-re)))
- (goto-char (match-end 0)))
- (and (not (or (looking-at scala-pattern-end-re)
- (scala-looking-at-special-identifier scala-pattern-end-special-re)))
- (let ((case-fold-search nil))
- (cond ((looking-at scala-capitalized-ident-re)
- (goto-char (match-end 0)))
- ((scala-match-and-skip-binding limit) t)))))
-
-
-(defvar scala-font-lock-keywords
+ (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-keywords-re 0 font-lock-keyword-face nil)
-
- ;; constants
- (,scala-constants-re
- 0 ,(if (boundp 'font-lock-constant-face)
- 'font-lock-constant-face
- 'font-lock-keyword-face)
- nil)
-
- ;; modules
- (,(concat "\\<\\(module\\|object\\)\\>\\s *\\(" scala-ident-re "\\)")
- (2 font-lock-variable-name-face nil))
-
- ;; type definitions
- (,(concat "\\<type\\>\\s *\\(" scala-ident-re "\\)")
- (1 font-lock-type-face nil))
-
- ;; variables
- ("\\<var\\>"
- (scala-match-and-skip-binding (goto-char (match-end 0))
- nil
- (1 font-lock-variable-name-face nil)
- (2 font-lock-type-face nil t)))
-
- ;; functions
- (,(concat "\\(^\\|[^(,]\\)\\s *\\<def\\>"
- "\\s *"
- "\\("
- scala-ident-re
- "\\)\\s *")
- (2 font-lock-function-name-face nil)
- (scala-match-and-skip-type-param (goto-char (match-end 0)) nil
- (1 font-lock-type-face nil t))
- (scala-match-and-skip-binding nil nil
- (1 font-lock-variable-name-face nil)
- (2 font-lock-type-face nil t))
- (scala-match-and-skip-result-type nil nil
- (0 font-lock-type-face nil)))
-
- ;; class definitions
- ("\\<\\(class\\|trait\\)\\>"
- (scala-match-and-skip-ident (goto-char (match-end 0)) nil
- (1 font-lock-type-face nil))
- (scala-match-and-skip-type-param nil nil
- (1 font-lock-type-face nil t))
- (scala-match-and-skip-binding nil nil
- (1 font-lock-variable-name-face nil)
- (2 font-lock-type-face nil t)))
-
- ;; "extends" and "with" clauses
- ("\\<\\(extends\\|with\\)\\>\\s *[^{]"
- (scala-match-and-skip-ident (goto-char (1- (match-end 0))) nil
- (0 font-lock-type-face nil))
- (scala-match-and-skip-type-param nil nil
- (1 font-lock-type-face nil t)))
-
- ;; patterns
- ("\\<\\(case\\|val\\)\\>\\s *"
- (scala-match-and-skip-pattern (goto-char (match-end 0)) nil
- (1 font-lock-variable-name-face nil)
- (2 font-lock-type-face nil t)))
+ (,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 "\\<object[ \t]+\\("
+ scala-syntax:id-re
+ "\\)")
+ 1 font-lock-constant-face)
+
+ ;; class, trait, object
+ (,(concat "\\<\\(class\\|trait\\)[ \t]+\\("
+ scala-syntax:id-re
+ "\\)")
+ 2 font-lock-type-face)
+
+ ;; ;; extends, with, new
+ ;; (,(concat "\\<\\(extends\\|with\\|new\\)[ \t]+\\([("
+ ;; scala-syntax:id-first-char-group "]\\)")
+ ;; (scala-font-lock:mark-simpleType (scala-font-lock:limit-simpleType
+ ;; (goto-char (match-beginning 2)))
+ ;; nil
+ ;; (0 font-lock-type-face nil t)))
+
+ ;; ;; ':'
+ ;; (,scala-syntax:colon-re
+ ;; (scala-font-lock:mark-simpleType (scala-font-lock:limit-simpleType
+ ;; (goto-char (match-end 2)))
+ ;; nil
+ ;; (0 font-lock-type-face nil t)))
+
+ ;; def
+ (,(concat "\\<def[ \t]+\\(" scala-syntax:id-re "\\)") 1 font-lock-function-name-face)
+
+ ;; VarDcl
+ ("\\<val[ \t]+\\([^:]\\)"
+ (scala-font-lock:mark-pattern1-part (scala-font-lock:limit-pattern2-list
+ (goto-char (match-beginning 1)))
+ nil
+ (1 font-lock-variable-name-face nil t)
+ (2 font-lock-constant-face nil t)
+ (3 font-lock-type-face nil t)))
+
+ ("\\<var[ \t]+\\([^:]\\)"
+ (scala-font-lock:mark-pattern1-part (scala-font-lock:limit-pattern2-list
+ (goto-char (match-beginning 1)))
+ nil
+ (1 scala-font-lock:var-face nil t)
+ (2 font-lock-constant-face nil t)
+ (3 font-lock-type-face nil t)
+ ))
+
+ ;; case (but not case class|object)
+ ("\\<case[ \t]+\\([^:]\\)"
+ (scala-font-lock:mark-pattern-part (scala-font-lock:limit-pattern
+ (goto-char (match-beginning 1)))
+ nil
+ (1 font-lock-variable-name-face nil t)
+ (2 font-lock-constant-face nil t)
+ (3 font-lock-type-face nil t)))
+
+ ;; type ascription (: followed by alpha type name)
+ (,(rx
+ (or (not (in "!#%&*+-/:<=>?@\\^|~")) 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-syntactic-keywords
- `((,scala-char-re (0 "\"" t nil))
- (scala-search-special-identifier-forward (0 "w" nil nil))))
+(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)
diff --git a/scala-mode-imenu.el b/scala-mode-imenu.el
new file mode 100644
index 0000000..f06a52e
--- /dev/null
+++ b/scala-mode-imenu.el
@@ -0,0 +1,134 @@
+;;; 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
diff --git a/scala-mode-indent.el b/scala-mode-indent.el
index ac3ec3d..d2237bd 100644
--- a/scala-mode-indent.el
+++ b/scala-mode-indent.el
@@ -1,228 +1,963 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-indent.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; scala-mode.el - Major mode for editing scala, indenting
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
-(provide 'scala-mode-indent)
+(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-mode-indent:step 2
- "Indentation step."
+(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 "\\<yield\\>")
+ ;; align with 'for'
+ (if (scala-syntax:search-backward-sexp "\\<for\\>")
+ (point)
+ (message "matching 'for' not found")
+ nil))
+ ((looking-at "\\<else\\>")
+ ;; align with 'if' or 'else if'
+ (if (scala-syntax:search-backward-sexp "\\<if\\>")
+ (if (scala-syntax:looking-back-token "\\<else\\>")
+ (goto-char (match-beginning 0))
+ (point))
+ nil))
+ ((looking-at "\\<catch\\>")
+ ;; align with 'try'
+ (if (scala-syntax:search-backward-sexp "\\<try\\>")
+ (point)
+ (message "matching 'try' not found")
+ nil))
+ ((looking-at "\\<finally\\>")
+ ;; align with 'try'
+ (if (scala-syntax:search-backward-sexp "\\<try\\>")
+ (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-parse-partial-sexp ()
- (parse-partial-sexp (point-min) (point)))
+(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))
-(defun scala-in-comment-p ()
- "Return t iff the point is inside a comment."
- ;; The two branches of the "if" below do not have the same behaviour
- ;; when the point is on the comment beginning/ending character(s).
- (or (scala-in-multi-line-comment-p)
- (scala-in-single-line-comment-p)))
+ ;; align list with first non-whitespace character
+ (skip-syntax-forward " ")
+ (point)))
-(defun scala-in-single-line-comment-p ()
- "Return t iff the point is inside a single line comment."
+(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 "\\<if\\>")
+ (scala-syntax:looking-back-token "\\<else\\>"))
+ (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
- (begin
- end
- subst
- match)
+ ((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
- (setq end (point))
- (beginning-of-line)
- (setq begin (point))
- (setq subst (buffer-substring begin end))
- (setq match (string-match "//" subst))
- (if match t nil))))
-
-(defun scala-in-multi-line-comment-p ()
- "Return t iff the point is inside a multi line comment."
- (if font-lock-mode
- (and (not (scala-in-single-line-comment-p))
- (eq (get-text-property (point) 'face) 'font-lock-comment-face))
- nil))
-
-
-(defun scala-in-string-p ()
- "Return t iff the point is inside a string."
- (if font-lock-mode
- (eq (get-text-property (point) 'face) 'font-lock-string-face)
- (let ((limit (point)))
(beginning-of-line)
- (loop while (search-forward-regexp "\\(^\\|[^\\\\]\\)\"" limit 'move)
- count (not (scala-in-comment-p)) into quotes
- finally return (oddp quotes)))))
+ (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-indentation ()
- "Return the suggested indentation for the current line."
+(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
- (beginning-of-line)
- (or (and (scala-in-comment-p)
- (not (= (char-after) ?\/))
- (scala-comment-indentation))
- (scala-indentation-from-following)
- (scala-indentation-from-preceding)
- (scala-indentation-from-block)
- 0)))
-
-(defun scala-comment-indentation ()
- ;; Return suggested indentation inside of a comment.
- (forward-line -1)
- (beginning-of-line)
- (skip-syntax-forward " ")
- (if (looking-at "/\\*")
- (+ 1 (current-column))
- (current-column)))
-
-(defun scala-block-indentation ()
- (let ((block-start-eol (scala-point-after (end-of-line)))
- (block-after-spc (scala-point-after (scala-forward-spaces))))
- (if (> block-after-spc block-start-eol)
- (progn
- (beginning-of-line)
- (when (search-forward ")" block-start-eol t)
- (scala-forward-spaces)
- (backward-sexp))
- (+ (current-indentation) scala-mode-indent:step))
+ (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-indentation-from-following ()
- ;; Return suggested indentation based on the following part of the
- ;; current expression. Return nil if indentation cannot be guessed.
- (save-excursion
- (scala-forward-spaces (scala-point-after (end-of-line)))
- (cond
- ((eobp) nil)
- ((= (char-syntax (char-after)) ?\))
- (let ((parse-sexp-ignore-comments t))
- (goto-char (1+ (scan-sexps (1+ (point)) -1))))
- (- (scala-block-indentation) scala-mode-indent:step))
- ((looking-at scala-expr-middle-re)
- ;; [...] this is a somewhat of a hack.
- (let ((matching-kw (cdr (assoc (match-string-no-properties 0)
- scala-expr-starter))))
- (while (and (search-backward-regexp matching-kw nil t)
- (or (scala-in-comment-p) (scala-in-string-p)))))
- (scala-move-if (backward-word 1)
- (looking-at scala-compound-expr-re))
- (current-column)))))
-
-(defun scala-indentation-from-preceding ()
- ;; Return suggested indentation based on the preceding part of the
- ;; current expression. Return nil if indentation cannot be guessed.
- (save-excursion
- (scala-backward-spaces)
- (and (not (bobp))
- (if (eq (char-syntax (char-before)) ?\()
- (scala-block-indentation)
- (progn
- (when (eq (char-before) ?\))
- (backward-sexp)
- (scala-backward-spaces))
- (scala-looking-at-backward scala-expr-start-re)))
- (+ (current-indentation) scala-mode-indent:step))))
-
-
-(defun scala-indentation-from-block ()
- ;; Return suggested indentation based on the current block.
+(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
- (let* ((state (scala-parse-partial-sexp))
- (block-start (nth 1 state)))
- (if (not block-start)
- 0
- (goto-char (1+ block-start))
- (scala-block-indentation)))))
-
-(defun scala-indent-line-to (column)
- "Indent current line to COLUMN and perhaps move point.
-The point is moved iff it is currently in the indentation, in which
-case it is brought to the end of that indentation. Otherwise it does
-not move."
- (if (<= (current-column) (current-indentation))
- (indent-line-to column)
- (save-excursion (indent-line-to column))))
-
-(defun scala-indent-line ()
- "Indent current line as smartly as possible.
-When called repeatedly, indent each time one stop further on the right."
- (interactive)
- (if (or (eq last-command this-command)
- (eq last-command 'scala-undent-line))
- (scala-indent-line-to (+ (current-indentation) scala-mode-indent:step))
- (let
- ((indentation (scala-indentation)))
- (scala-indent-line-to indentation))))
-
-(defun scala-undent-line ()
- "Indent line to previous tab stop."
- (interactive)
- (scala-indent-line-to (max 0 (- (current-indentation) scala-mode-indent:step))))
+ (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-electric-brace ()
- "Insert a brace, and if alone on a non-comment line, reindent."
- (interactive)
- (let ((on-empty-line-p (save-excursion
- (beginning-of-line)
- (looking-at "^\\s *$"))))
- ;; Calling self-insert-command will blink to the matching open-brace
- ;; (if blink-matching-paren is enabled); we first indent, then
- ;; call self-insert-command, so that the close-brace is correctly
- ;; positioned during the blink.
- (when on-empty-line-p
- (insert "}")
- (scala-indent-line)
- (delete-backward-char 1))
- (call-interactively 'self-insert-command)))
-
-
-(defun scala-newline ()
- (interactive)
- (if (scala-in-multi-line-comment-p)
- (progn
- (newline-and-indent)
- (insert "* "))
- (newline)))
+(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)
diff --git a/scala-mode-inf.el b/scala-mode-inf.el
deleted file mode 100644
index 1047714..0000000
--- a/scala-mode-inf.el
+++ /dev/null
@@ -1,201 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-inf.el - Interaction with a Scala interpreter.
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-inf)
-
-
-(require 'comint)
-
-(defgroup scala-mode-inf
- nil
- "Mode to interact with a Scala interpreter."
- :group 'scala
- :tag "Inferior Scala")
-
-(defcustom scala-interpreter "scala"
- "The interpreter that `run-scala' should run. This should
- be a program in your PATH or the full pathname of the scala interpreter."
- :type 'string
- :group 'scala-mode-inf)
-
-(defconst scala-inf-buffer-name "*inferior-scala*")
-
-(define-derived-mode scala-mode-inf comint-mode "Inferior Scala"
- "Major mode for interacting with a Scala interpreter.
-
-\\{inferior-scala-mode-map\\}"
- (define-key scala-mode-inf-map [(meta return)] 'comint-accumulate)
-
- ;; Comint configuration
- (make-local-variable 'comint-input-sender)
- (setq comint-input-sender 'scala-input-sender))
-
-(defun scala-input-sender (proc string)
- (comint-send-string proc string)
- ;; (comint-send-string proc "\nemacs:end\n")) ;; Heineman's contrib (06/03/2007)
- (comint-send-string proc "\n"))
-
-;;;###autoload
-(defun scala-interpreter-running-p-1 ()
- ;; True iff a Scala interpreter is currently running in a buffer.
- (comint-check-proc scala-inf-buffer-name))
-
-(defun scala-check-interpreter-running ()
- (unless (scala-interpreter-running-p-1)
- (error "Scala interpreter not running")))
-
-;;;###autoload
-(defun scala-run-scala (cmd-line)
- "Run a Scala interpreter in an Emacs buffer"
- (interactive (list (if current-prefix-arg
- (read-string "Scala interpreter: " scala-interpreter)
- scala-interpreter)))
- (unless (scala-interpreter-running-p-1)
- (setq scala-interpreter cmd-line)
- (let ((cmd/args (split-string cmd-line)))
- (set-buffer
- (apply 'make-comint "inferior-scala" (car cmd/args) nil (cdr cmd/args))))
- (scala-mode-inf)
- (pop-to-buffer scala-inf-buffer-name)))
-
-(defun scala-send-string (str &rest args)
- ;; Send string to interpreter
- (comint-send-string scala-inf-buffer-name (apply 'format str args))
- ;; (comint-send-string scala-inf-buffer-name "\nemacs:end\n")) Heineman's contrib (06/03/2007)
- (comint-send-string scala-inf-buffer-name "\n"))
-
-;;;###autoload
-(defun scala-switch-to-interpreter ()
- "Switch to buffer containing the interpreter"
- (interactive)
- (scala-check-interpreter-running)
- (switch-to-buffer scala-inf-buffer-name))
-
-(defvar scala-tmp-file nil)
-
-;;;###autoload
-(defun scala-eval-region (start end)
- "Send current region to Scala interpreter."
- (interactive "r")
- (scala-check-interpreter-running)
- (comint-send-region scala-inf-buffer-name start end)
- (comint-send-string scala-inf-buffer-name "\n"))
-
-;;;###autoload
-(defun scala-eval-definition ()
- "Send the current 'definition' to the Scala interpreter.
-This function's idea of a definition is the block of text ending
-in the current line (or the first non-empty line going
-backwards), and begins in the first line that is not empty and
-does not start with whitespace or '{'.
-
-For example:
-
-println( \"aja\")
-println( \"hola\" )
-
-if the cursor is somewhere in the second print statement, the
-interpreter should output 'hola'.
-
-In the following case, if the cursor is in the second line, then
-the complete function definition will be send to the interpreter:
-
-def foo =
- 1 + 2
-"
- (interactive)
- (save-excursion
- ;; find the first non-empty line
- (beginning-of-line)
- (while (and (not (= (point) (point-min)))
- (looking-at "\\s-*$"))
- (next-line -1))
- (end-of-line)
- (let ((end (point)))
- ;; now we need to find the start
- (beginning-of-line)
- (while (and (not (= (point) (point-min)))
- (looking-at (mapconcat '(lambda (x) x)
- '("^$" ; empty lines
- "^\\s-+" ; empty lines or lines that start with whitespace
- "^\\s-*}") ; lines that start with a '}'
- "\\|")))
- (next-line -1)
- (beginning-of-line))
- (message "region %s %s" (point) end)
- (scala-eval-region (point) end))))
-
-;;;###autoload
-(defun scala-eval-buffer ()
- "Send whole buffer to Scala interpreter."
- (interactive)
- (scala-eval-region (point-min) (point-max)))
-
-(defvar scala-prev-l/c-dir/file nil
- "Caches the last (directory . file) pair.
-Caches the last pair used in the last scala-load-file.
-Used for determining the default in the next one.")
-
-;;;###autoload
-(defun scala-load-file (file-name)
- "Load a file in the Scala interpreter."
- (interactive (comint-get-source "Load Scala file: " scala-prev-l/c-dir/file
- '(scala-mode) t))
- (scala-check-interpreter-running)
- (comint-check-source file-name)
- (setq scala-prev-l/c-dir/file (cons (file-name-directory file-name)
- (file-name-nondirectory file-name)))
- (scala-send-string ":load %s" file-name))
-
-;;;###autoload
-(defun scala-quit-interpreter ()
- "Quit Scala interpreter."
- (interactive)
- (scala-check-interpreter-running)
- (scala-send-string "\n:quit"))
-
diff --git a/scala-mode-lib.el b/scala-mode-lib.el
index ef2a6b2..538f3a0 100644
--- a/scala-mode-lib.el
+++ b/scala-mode-lib.el
@@ -1,114 +1,26 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-lib.el - Libraries and macroes used by the scala mode.
+;;; 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
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
+(defvar scala-mode:debug-messages
+ "If true, some debug messages may be printed printed."
+ nil)
-;;; License
+(defmacro scala-lib:column-after (&rest body)
+ `(save-excursion
+ ,@body
+ (current-column)))
-;; 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.
+(defmacro scala-lib:point-after (&rest body)
+ `(save-excursion
+ ,@body
+ (point)))
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-lib)
-
-(eval-when-compile
- (require 'scala-mode-constants))
-
-
-(defmacro scala-mode-lib:define-keys (key-map &rest key-funcs)
- "Define key bindings for KEY-MAP (create KEY-MAP, if it does
-not exist."
- `(progn
- (unless (boundp ',key-map)
- (setf ,key-map (make-keymap)))
- ,@(mapcar
- #'(lambda (key-func)
- `(define-key ,key-map ,(first key-func) ,(second key-func)))
- key-funcs)))
-
-
-(defun scala-special-char-p (char)
- (and char
- (string-match scala-all-special-char-re (string char))))
-
-(defun scala-looking-at-special-identifier (regexp)
- (and (not (scala-special-char-p (char-before)))
- (looking-at regexp)
- (not (scala-special-char-p (char-after (match-end 0))))))
-
-
-(defun scala-search-special-identifier-forward (limit)
- (ignore-errors
- (while (and (search-forward-regexp scala-special-ident-re limit)
- (save-match-data
- (string-match scala-comment-begin-or-end-re
- (match-string-no-properties 0)))))
- t))
-
-
-(defun scala-mode-find-clstrtobj-name-doc ()
+(defun scala-lib:delete-trailing-whitespace ()
(save-excursion
- (if (re-search-forward "\\(class\\|object\\|trait\\)[ \t\n]+\\([a-zA-Z0-9_:=]+\\)[ \t\n]*" nil t)
-
- (buffer-substring (match-beginning 2) (match-end 2))
- "NONAME")))
+ (end-of-line)
+ (skip-syntax-backward " ")
+ (unless (bolp)
+ (delete-char (- (line-end-position) (point))))))
-
-(defun scala-mode-def-and-args-doc ()
- (save-excursion
- (if (re-search-forward
- (concat
- ;; function name
- "[ \t\n]*def[ \t\n]+\\([a-zA-Z0-9_:=]+\\)[ \t\n]*"
-
- ;; arguments
- "\\((\\([a-zA-Z0-9_:* \t\n]*\\))\\)?"
- ) nil t)
-
- ;; TODO: output args in a sane format to use in yasnippet, look at doxymancs line 1441
- (let* ((func (buffer-substring (match-beginning 1) (match-end 1)))
- ;(args (buffer-substring (match-beginning 3) (match-end 3)))
- )
- (concat "${1:" func "} $0"))
- "${1:name} $0")))
-
-
-(defun scala-mode-file-doc ()
- (file-name-nondirectory buffer-file-name))
+(provide 'scala-mode-lib)
diff --git a/scala-mode-map.el b/scala-mode-map.el
new file mode 100644
index 0000000..615c8fd
--- /dev/null
+++ b/scala-mode-map.el
@@ -0,0 +1,28 @@
+;;; 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)
diff --git a/scala-mode-navigation.el b/scala-mode-navigation.el
deleted file mode 100644
index ba4d586..0000000
--- a/scala-mode-navigation.el
+++ /dev/null
@@ -1,193 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-navigation.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-navigation)
-
-(require 'scala-mode-constants)
-
-(defun scala-when-looking-at* (regexp &optional thunk)
- (let ((saved-match-data (match-data)))
- (if (looking-at regexp)
- (progn (goto-char (match-end 0))
- (set-match-data saved-match-data)
- (or (not thunk) (funcall thunk)))
- (set-match-data saved-match-data)
- nil)))
-
-(defmacro scala-when-looking-at (regexp &rest body)
- (if body
- `(scala-when-looking-at* ,regexp (lambda () ,@body))
- `(scala-when-looking-at* ,regexp)))
-
-(defun scala-forward-spaces (&optional limit)
- (if limit
- (save-restriction
- (narrow-to-region (point) limit)
- (forward-comment 100000))
- (forward-comment 100000)))
-
-(defun scala-backward-spaces ()
- (forward-comment -100000))
-
-(defun scala-looking-at-backward (re)
- (save-excursion
- (when (= 0 (skip-syntax-backward "w_")) (backward-char))
- (looking-at re)))
-
-(defmacro scala-point-after (&rest body)
- `(save-excursion
- ,@body
- (point)))
-
-
-(defmacro scala-move-if (&rest body)
- (let ((pt-sym (make-symbol "point"))
- (res-sym (make-symbol "result")))
- `(let ((,pt-sym (point))
- (,res-sym ,(cons 'progn body)))
- (unless ,res-sym (goto-char ,pt-sym))
- ,res-sym)))
-
-(defun scala-forward-ident ()
- ;; Move forward over an identifier.
- (scala-forward-spaces)
- (if (looking-at scala-ident-re)
- (goto-char (match-end 0))
- (forward-char))
- t)
-
-(defun scala-backward-ident ()
- ;; Move backward over an identifier.
- (scala-backward-spaces)
- (if (scala-looking-at-backward scala-ident-re)
- (goto-char (match-beginning 0))
- (backward-char))
- t)
-
-(defun scala-forward-qual-ident ()
- ;; Move forward over a qualifier identifier.
- (scala-forward-spaces)
- (if (looking-at scala-qual-ident-re)
- (goto-char (match-end 0))
- (forward-char))
- t)
-
-(defun scala-backward-qual-ident ()
- ;; Move backward over a qualifier identifier.
- (scala-backward-spaces)
- (if (scala-looking-at-backward scala-qual-ident-re)
- (goto-char (match-beginning 0))
- (backward-char))
- t)
-
-(defun scala-forward-simple-type ()
- ;; Move forward over a simple type (as defined by the grammar).
- ;; Works only when point is at the beginning of a simple type
- ;; (modulo initial spaces/comments).
- (cond ((eobp) nil)
- ((= (char-after) ?\()
- ;; Parenthesized type
- (forward-sexp)
- t)
- (t
- ;; Type designator
- (scala-forward-qual-ident)
- (scala-forward-spaces)
- (cond ((eobp) nil)
- ((= (char-after) ?\[)
- ;; Type arguments
- (forward-sexp))
- ((= (char-after) ?\#)
- ;; Type selection
- (forward-char)
- (scala-forward-ident)))
- t)))
-
-(defun scala-forward-type1 ()
- ;; Move forward over a type1 (as defined by the grammar).
- ;; Works only when point is at the beginning of a type (modulo
- ;; initial spaces/comments).
- (scala-forward-spaces)
- (scala-when-looking-at "\\<class\\>"
- (forward-word 1) (scala-forward-spaces))
- (scala-forward-simple-type)
- (while (scala-when-looking-at "\\s *\\<with\\>\\s *")
- (if (and (not (eobp)) (= (char-after) ?\{))
- (forward-sexp) ;skip refinement
- (scala-forward-simple-type)))
- t)
-
-(defun scala-forward-type ()
- ;; Move forward over a type.
- (cond ((eobp) nil)
- ((= (char-after) ?\()
- ;; Function type (several arguments)
- (forward-sexp)
- (scala-when-looking-at "\\s *=>\\s *" (scala-forward-type))
- t)
- (t
- ;; Type1 or function type with one argument
- (scala-forward-type1)
- (scala-when-looking-at "\\s *=>\\s *" (scala-forward-type))
- t)))
-
-(defun scala-forward-type-param ()
- ;; Move over a type parameter
- ;; variance
- (scala-when-looking-at "\\s *[-+]\\s *")
- (scala-forward-ident)
- ;; bounds
- (while (scala-when-looking-at "\\s *[<>][:%]\\s *")
- (scala-forward-type))
- t)
-
-(defun scala-forward-literal ()
- ;; Move forward over an integer, float, character or string literal.
- (scala-forward-spaces)
- (scala-when-looking-at scala-literal-re)
- t)
diff --git a/scala-mode-paragraph.el b/scala-mode-paragraph.el
new file mode 100644
index 0000000..06fc7b2
--- /dev/null
+++ b/scala-mode-paragraph.el
@@ -0,0 +1,110 @@
+;;; 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)
diff --git a/scala-mode-prettify-symbols.el b/scala-mode-prettify-symbols.el
new file mode 100644
index 0000000..73dd259
--- /dev/null
+++ b/scala-mode-prettify-symbols.el
@@ -0,0 +1,94 @@
+;;; 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
diff --git a/scala-mode-syntax.el b/scala-mode-syntax.el
new file mode 100644
index 0000000..1817868
--- /dev/null
+++ b/scala-mode-syntax.el
@@ -0,0 +1,1047 @@
+;;;; 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 "\\<super\\>")
+ (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 "\\<this\\>")
+ (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 ('<!' and '<?')
+ (concat "\\(^\\|[^" scala-syntax:opchar-group "]\\)"
+ scala-syntax:reserved-symbols-unsafe-re
+ "\\(" scala-syntax:after-reserved-symbol-re "\\)"))
+
+(defconst scala-syntax:colon-re
+ (concat "\\(^\\|[^" scala-syntax:opchar-group "]\\)"
+ "\\(:\\)"
+ "\\(" scala-syntax:after-reserved-symbol-re "\\)"))
+
+
+(defconst scala-syntax:override-unsafe-re
+ (regexp-opt '("override") 'words))
+
+(defconst scala-syntax:override-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:override-unsafe-re "\\)"))
+
+(defconst scala-syntax:abstract-unsafe-re
+ (regexp-opt '("abstract") 'words))
+
+(defconst scala-syntax:abstract-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:abstract-unsafe-re "\\)"))
+
+(defconst scala-syntax:final-unsafe-re
+ (regexp-opt '("final") 'words))
+
+(defconst scala-syntax:final-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:final-unsafe-re "\\)"))
+
+(defconst scala-syntax:sealed-unsafe-re
+ (regexp-opt '("sealed") 'words))
+
+(defconst scala-syntax:sealed-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:sealed-unsafe-re "\\)"))
+
+(defconst scala-syntax:implicit-unsafe-re
+ (regexp-opt '("implicit") 'words))
+
+(defconst scala-syntax:implicit-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:implicit-unsafe-re "\\)"))
+
+(defconst scala-syntax:lazy-unsafe-re
+ (regexp-opt '("lazy") 'words))
+
+(defconst scala-syntax:lazy-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:lazy-unsafe-re "\\)"))
+
+(defconst scala-syntax:private-unsafe-re
+ (regexp-opt '("private") 'words))
+
+(defconst scala-syntax:private-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:private-unsafe-re "\\)"))
+
+(defconst scala-syntax:protected-unsafe-re
+ (regexp-opt '("protected") 'words))
+
+(defconst scala-syntax:protected-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:protected-unsafe-re "\\)"))
+
+(defconst scala-syntax:modifiers-unsafe-re
+ (regexp-opt '("override" "abstract" "final" "sealed" "implicit" "lazy"
+ "private" "protected") 'words))
+
+(defconst scala-syntax:modifiers-re
+ (concat "\\(^\\|[^`'_]\\)\\(" scala-syntax:modifiers-unsafe-re "\\)"))
+
+(defconst scala-syntax:body-start-re
+ (concat "=" scala-syntax:end-of-code-line-re)
+ "A regexp for detecting if a line ends with '='")
+
+(defconst scala-syntax:list-keywords-re
+ (regexp-opt '("var" "val" "import") 'words)
+ ("Keywords that can start a list"))
+
+(defconst scala-syntax:case-re
+ "\\<case\\>")
+
+(defconst scala-syntax:for-re
+ "\\<for\\>")
+
+(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 '("</"))
+ (member 0 (mapcar (lambda (regexp) (string-match regexp match)) '("^*+/$" "^//.*$" "^/\\*+$")))
+ (equal 2 (syntax-class (syntax-after match-end)))
+ (equal 2 (syntax-class (syntax-after (1- match-beg)))))
+ (put-text-property match-beg match-end 'syntax-table '(3 . nil)))))))
+
+(defun scala-syntax:propertize-quotedid (start end)
+ "Mark all `scala-syntax:quotedid-re' as symbol constituents (syntax 3)"
+ (save-excursion
+ (goto-char start)
+ (while (re-search-forward scala-syntax:quotedid-re end t)
+ (scala-syntax:put-syntax-table-property 0 '(3 . nil)))))
+
+(defun scala-syntax:propertize-dollar (start end)
+ "Mark all $ occurences as punctuation (syntax 1)"
+ (save-excursion
+ (goto-char start)
+ (while (re-search-forward "\\$" end t)
+ (scala-syntax:put-syntax-table-property 0 '(1 . nil)))))
+
+(defun scala-syntax:propertize (start end)
+ "See syntax-propertize-function"
+ (scala-syntax:propertize-char-and-string-literals start end)
+ (scala-syntax:propertize-shell-preamble start end)
+ (scala-syntax:propertize-underscore-and-idrest start end)
+ (scala-syntax:propertize-special-symbols start end)
+ (scala-syntax:propertize-quotedid start end)
+ (scala-syntax:propertize-dollar start end))
+
+;;;;
+;;;; Syntax navigation functions
+;;;;
+
+(defun scala-syntax:beginning-of-code-line ()
+ (interactive)
+ "Move to the beginning of code on the line, or to the end of
+the line, if the line is empty. Return the new point. Not to be
+called on a line whose start is inside a comment, i.e. a comment
+begins on the previous line and continues past the start of this
+line."
+ ;; TODO: make it work even if the start IS inside a comment
+ (beginning-of-line)
+ (let ((eol (line-end-position))
+ (pos (point)))
+
+ (while (and (forward-comment 1)
+ (< (point) eol))
+ (setq pos (point)))
+ ;; Now we are either on a different line or at eol.
+ ;; Pos is the last point one the starting line.
+ (if (> (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)
diff --git a/scala-mode-ui.el b/scala-mode-ui.el
deleted file mode 100644
index 8dd355a..0000000
--- a/scala-mode-ui.el
+++ /dev/null
@@ -1,159 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-ui.el - Menu entries and keyboard shortcuts for scala mode
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-ui)
-
-(require 'easymenu)
-(require 'scala-mode-lib)
-
-(eval-when-compile
- (require 'scala-mode-inf))
-
-(eval-and-compile
- (defcustom scala-mode-ui:prefix-key "\C-c"
- "Key prefix for scala mode."
- :group 'scala))
-
-(defmacro scala-mode-ui:key (key)
- "Simple macro for appending 'scala-mode-prefix-key' to key commands"
- `(kbd ,(concat scala-mode-ui:prefix-key " " key)))
-
-;;; Helper functions
-
-(defun scala-mode-ui:interpreter-running-p ()
- "True iff a Scala interpreter is currently running in a buffer."
- ;; The following makes sure that we do not autoload
- ;; scala-mode-inf just to check if the interpreter is running.
- (and (fboundp 'scala-mode-inf)
- (let ((ism-def (symbol-function 'scala-mode-inf)))
- (not (and (consp ism-def) (eq (car ism-def) 'autoload))))
- (scala-interpreter-running-p-1)))
-
-;;; Menubar
-
-(scala-mode-lib:define-keys scala-mode-menu-bar-map
-
- ([scala] (cons "Scala" (make-sparse-keymap "ScalaMode")))
-
- ([scala version] '(menu-item "Version" (lambda () (interactive) (message "Using scala mode version %s (%s)" scala-mode-version scala-mode-svn-revision)) ))
- ([scala report-bug] '(menu-item "Report bug" scala-mode:report-bug))
- ([scala customize] '(menu-item "Customize" (lambda () (interactive) (customize-group 'scala))))
- ([scala browse-api] '(menu-item "Browse Scala API" scala-mode:browse-api))
- ([scala browse-website] '(menu-item "Browse Scala Website" scala-mode:browse-web-site))
-
- ([scala sep0] '("---"))
-
- ([scala feature] (cons "Features" (make-sparse-keymap "Features")))
-
- ([scala feature apropos] '(menu-item "Tag apropos" tags-apropos))
- ([scala feature search] '(menu-item "Tag search" tags-search))
- ([scala feature find] '(menu-item "Tag find" find-tag))
- ([scala feature comp] '(menu-item "Tag complete word" scala-mode-feature-tags-complete))
- ([scala feature load] '(menu-item "Load TAGS file" scala-mode-feature-tags-load))
- ([scala feature create] '(menu-item "Create TAGS file" scala-mode-feature-tags-create))
-
- ([scala feature sep1] '("---"))
-
- ([scala feature speedbar] '(menu-item "Speedbar Focus" speedbar-get-focus))
-
- ([scala feature sep0] '("---"))
-
- ([scala feature electric] '(menu-item "Toggle Scala Electric Mode" scala-electric-mode
- :button (:toggle . (scala-mode-feature-electric-active-p))
- :help "Toggle on/off the electric insert mode for Scala files"))
-
- ([scala sep1] '("---"))
-
- ([scala eval-buf] '(menu-item "Evaluate buffer" scala-eval-buffer :enable (scala-mode-ui:interpreter-running-p) ))
- ([scala eval-reg] '(menu-item "Evaluate region" scala-eval-region :enable (and (scala-mode-ui:interpreter-running-p) mark-active)))
- ([scala switch-interp] '(menu-item "Switch to interpreter" scala-switch-to-interpreter :enable (scala-mode-ui:interpreter-running-p) ))
- ([scala load-file] '(menu-item "Load file in interpreter" scala-load-file :enable (scala-mode-ui:interpreter-running-p) ))
- ([scala quit-interp] '(menu-item "Quit interpreter" scala-quit-interpreter :enable (scala-mode-ui:interpreter-running-p) ))
- ([scala run-interp] '(menu-item "Run interpreter..." scala-run-scala :enable (not (scala-mode-ui:interpreter-running-p)) ))
-
-)
-
-
-;;; Shortcuts
-
-(defvar scala-mode-map
- (let ((map (make-keymap)))
- map))
-
-(scala-mode-lib:define-keys scala-mode-map
-
- ;; Attach Menubar
- ([menu-bar] scala-mode-menu-bar-map)
-
- ;; Attach keyboard Shortcuts
- ([(control tab)] 'scala-undent-line)
- ([backspace] 'backward-delete-char-untabify)
-
- ("\r" 'scala-newline)
-
- ([f1] 'speedbar-get-focus)
-
- ([(control c)(control l)] 'scala-load-file)
- ([(control c)(control r)] 'scala-eval-region)
- ([(control c)(control b)] 'scala-eval-buffer)
-
- ([(control c)(control c)] 'comment-region)
-
- ("}" 'scala-electric-brace)
-
- ((scala-mode-ui:key "t n") 'scala-mode-feature-tags-create)
- ((scala-mode-ui:key "t l") 'scala-mode-feature-tags-load)
- ((scala-mode-ui:key "t c") 'scala-mode-feature-tags-complete)
- ((scala-mode-ui:key "t s") 'tags-search)
- ((scala-mode-ui:key "t a") 'tags-apropos)
- )
-
-
-
-
-
diff --git a/scala-mode-variables.el b/scala-mode-variables.el
deleted file mode 100644
index 6aa37e5..0000000
--- a/scala-mode-variables.el
+++ /dev/null
@@ -1,55 +0,0 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode-feature.el -
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'scala-mode-variables)
-
-;; Feature specific variables that need to be shared!
-
-; define scala-mode-hook
-(defvar scala-mode-hook nil
- "Hook to run after installing scala mode")
diff --git a/scala-mode.el b/scala-mode.el
index 2ff0f9b..bfe55f3 100644
--- a/scala-mode.el
+++ b/scala-mode.el
@@ -1,207 +1,182 @@
-;;; -*-Emacs-Lisp-*-
-;;; scala-mode.el - Major mode for editing Scala code.
-
-;; Copyright (C) 2009-2011 Scala Dev Team at EPFL
-;; Authors: See AUTHORS file
-;; Keywords: scala languages oop
-
-;;; License
-
-;; 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.
-
-;;; Code
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; scala-mode.el --- Major mode for editing Scala
-(provide 'scala-mode)
+;; Copyright (c) 2012 Heikki Vesalainen
+
+;; Homepage: https://github.com/hvesalai/emacs-scala-mode
+;; Keywords: languages
+;; Package-Version: 0.23
+;; Package-Requires: ()
-(require 'cl)
+;;; Commentary:
+;;
+;;; Code:
-(require 'scala-mode-constants)
-(require 'scala-mode-variables)
(require 'scala-mode-lib)
-(require 'scala-mode-navigation)
+(require 'scala-mode-syntax)
+(require 'scala-mode-paragraph)
(require 'scala-mode-indent)
(require 'scala-mode-fontlock)
-(require 'scala-mode-ui)
-(require 'scala-mode-feature)
+(require 'scala-mode-map)
+(require 'scala-mode-imenu)
+(require 'scala-mode-prettify-symbols)
-;;; Customization and Variables
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(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
- "Mode for editing Scala code."
+ "A programming mode for the Scala language 2.9"
:group 'languages)
-(defcustom scala-mode:api-url "http://www.scala-lang.org/docu/files/api/index.html"
- "URL to the online Scala documentation"
- :type 'string
- :group 'scala)
-
-(defconst scala-mode-version "0.5.99.5")
-(defconst scala-mode-svn-revision "$Revision: 21917 $")
-(defconst scala-bug-e-mail "scala@listes.epfl.ch")
-(defconst scala-web-url "http://scala-lang.org/")
-
-
-;;; Helper functions/macroes
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-(defun scala-mode:browse-web-site ()
- "Browse the Scala home-page"
- (interactive)
- (require 'browse-url)
- (browse-url scala-web-url))
-
-
-(defun scala-mode:browse-api ()
- "Browse the Scala API"
- (interactive)
- (require 'browse-url)
- (browse-url scala-mode:api-url))
+(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))
-(defun scala-mode:report-bug ()
- "Report a bug to the author of the Scala mode via e-mail.
-The package used to edit and send the e-mail is the one selected
-through `mail-user-agent'."
+;;;###autoload
+(defun scala-mode:goto-start-of-code ()
+ "Go to the start of the real code in the file: object, class or trait."
(interactive)
- (require 'reporter)
- (let ((reporter-prompt-for-summary-p t))
- (reporter-submit-bug-report
- scala-bug-e-mail
- (concat "Emacs Scala mode v" scala-mode-version)
- '(scala-indent-step))))
-
-
-
-
-
-(defvar scala-mode-abbrev-table nil
- "Abbrev table in use in `scala-mode' buffers.")
-(define-abbrev-table 'scala-mode-abbrev-table nil)
-
-
-(defvar scala-mode-syntax-table nil
- "Syntax table used in `scala-mode' buffers.")
-(when (not scala-mode-syntax-table)
- (setq scala-mode-syntax-table (make-syntax-table))
- ;; strings and character literals
- (modify-syntax-entry ?\" "\"" scala-mode-syntax-table)
- (modify-syntax-entry ?\\ "\\" scala-mode-syntax-table)
-
- ;; different kinds of "parenthesis"
- (modify-syntax-entry ?\( "()" scala-mode-syntax-table)
- (modify-syntax-entry ?\[ "(]" scala-mode-syntax-table)
- (modify-syntax-entry ?\{ "(}" scala-mode-syntax-table)
- (modify-syntax-entry ?\) ")(" scala-mode-syntax-table)
- (modify-syntax-entry ?\] ")[" scala-mode-syntax-table)
- (modify-syntax-entry ?\} "){" scala-mode-syntax-table)
-
- ;; special characters
- (modify-syntax-entry ?\_ "_" scala-mode-syntax-table)
-
- (dolist (char scala-all-special-chars)
- (modify-syntax-entry char "." scala-mode-syntax-table))
-
- (modify-syntax-entry ?\. "." scala-mode-syntax-table)
-
- ;; comments
- ;; the `n' means that comments can be nested
- (modify-syntax-entry ?\/ ". 124nb" scala-mode-syntax-table)
- (modify-syntax-entry ?\* ". 23n" scala-mode-syntax-table)
- (modify-syntax-entry ?\n "> bn" scala-mode-syntax-table)
- (modify-syntax-entry ?\r "> bn" scala-mode-syntax-table))
+ (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.
-;;; Mode
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+When started, runs `scala-mode-hook'.
-;;;###autoload
-(defun scala-mode ()
- "Major mode for editing Scala code.
-When started, run `scala-mode-hook'.
\\{scala-mode-map}"
- (interactive)
- ;; set up local variables
- (kill-all-local-variables)
- (make-local-variable 'font-lock-defaults)
- (make-local-variable 'paragraph-separate)
- (make-local-variable 'paragraph-start)
- (make-local-variable 'paragraph-ignore-fill-prefix)
- (make-local-variable 'require-final-newline)
- (make-local-variable 'comment-start)
- (make-local-variable 'comment-end)
- (make-local-variable 'comment-start-skip)
- (make-local-variable 'comment-end-skip)
- (make-local-variable 'comment-column)
- ;(make-local-variable 'comment-indent-function)
- (make-local-variable 'indent-line-function)
- ;;
- (set-syntax-table scala-mode-syntax-table)
- (setq major-mode 'scala-mode
- mode-name "Scala"
- local-abbrev-table scala-mode-abbrev-table
- font-lock-defaults '(scala-font-lock-keywords
- nil
- nil
- ((?\_ . "w"))
- nil
- (font-lock-syntactic-keywords . scala-font-lock-syntactic-keywords)
- (parse-sexp-lookup-properties . t))
- paragraph-separate (concat "^\\s *$\\|" page-delimiter)
- paragraph-start (concat "^\\s *$\\|" page-delimiter)
- paragraph-ignore-fill-prefix t
- require-final-newline t
- comment-start "// "
- comment-end ""
- comment-start-skip "/\\*+ *\\|//+ *"
- comment-end-skip " *\\*+/\\| *"
- comment-column 40
-; comment-indent-function 'scala-comment-indent-function
- indent-line-function 'scala-indent-line
- )
-
+ :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)
- (turn-on-font-lock)
- (scala-mode-feature-install)
- (if scala-mode-hook
- (run-hooks 'scala-mode-hook)))
-
-
+ ;; 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
diff --git a/test/scala-mode-test.el b/test/scala-mode-test.el
new file mode 100644
index 0000000..8a7a195
--- /dev/null
+++ b/test/scala-mode-test.el
@@ -0,0 +1,178 @@
+(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 = <td>hello</td>"
+ "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<T>"
+ "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"))
diff --git a/test/test-helper.el b/test/test-helper.el
new file mode 100644
index 0000000..7eeb038
--- /dev/null
+++ b/test/test-helper.el
@@ -0,0 +1 @@
+(require 'scala-mode)