diff --git a/scala-mode/AUTHORS b/scala-mode/AUTHORS new file mode 100644 index 0000000..640c8ad --- /dev/null +++ b/scala-mode/AUTHORS @@ -0,0 +1,18 @@ +In Emacs, this file should be read in -*- Outline -*- mode. +$Id: AUTHORS 17069 2009-02-10 08:30:51Z nielsen $ + +Below is a list of people who have made changes or contributed to the +scala emacs mode. + +* Main mode developers +** Michel Schinz +** Anders Bach Nielsen + + +* Contributions +** Iulian Dragos +** Stephane Micheloud +** Victor Rodriguez +** ? +** Hemant Kumar +** Ulrick Müller diff --git a/scala-mode/FUTURE b/scala-mode/FUTURE new file mode 100644 index 0000000..f0596ff --- /dev/null +++ b/scala-mode/FUTURE @@ -0,0 +1,125 @@ +-*- Outline -*- +$Id: FUTURE 16681 2008-12-01 22:17:46Z nielsen $ + +* 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/scala-mode/Makefile b/scala-mode/Makefile new file mode 100644 index 0000000..5bbbc50 --- /dev/null +++ b/scala-mode/Makefile @@ -0,0 +1,65 @@ +############################################################-*-Makefile-*-#### +# Makefile for compiling the major mode of Emacs +############################################################################## +# $Id: Makefile 16681 2008-12-01 22:17:46Z nielsen $ + +############################################################################## +# Configuration + +ROOT = . + +SOURCE_DIR = $(ROOT) + +############################################################################## +# Variables + +# 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_SOURCES += $(ELISP_FILES:%=$(SOURCE_DIR)/%.el) + +############################################################################## + +RM ?= rm -f +TOUCH ?= touch + +############################################################################## +# Commands + +all: .latest-build + +clean: + $(RM) *.elc .latest-* autoloads.el + +.PHONY: all +.PHONY: clean + +############################################################################## +# Rules + +.latest-build: $(ELISP_SOURCES) + $(ELISP_COMMAND) $(ELISP_OPTIONS) $(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 diff --git a/scala-mode/README b/scala-mode/README new file mode 100644 index 0000000..d5163be --- /dev/null +++ b/scala-mode/README @@ -0,0 +1,77 @@ +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. + + +* Version + +$Id: README 16681 2008-12-01 22:17:46Z nielsen $ diff --git a/scala-mode/contrib/README b/scala-mode/contrib/README new file mode 100644 index 0000000..03818f2 --- /dev/null +++ b/scala-mode/contrib/README @@ -0,0 +1,28 @@ +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/scala-mode/contrib/dot-ctags b/scala-mode/contrib/dot-ctags new file mode 100644 index 0000000..09f68ff --- /dev/null +++ b/scala-mode/contrib/dot-ctags @@ -0,0 +1,11 @@ +--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/scala-mode/scala-mode-auto.el b/scala-mode/scala-mode-auto.el new file mode 100644 index 0000000..5a26d30 --- /dev/null +++ b/scala-mode/scala-mode-auto.el @@ -0,0 +1,88 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-auto.el - Autoloads file for the scala mode + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-auto.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-constants.el b/scala-mode/scala-mode-constants.el new file mode 100644 index 0000000..8d705fd --- /dev/null +++ b/scala-mode/scala-mode-constants.el @@ -0,0 +1,205 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-constants.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-constants.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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 + "\\") + +(defconst scala-comment-begin-or-end-re + (concat "\\(" "^/\\*.*" "\\|" "^//.*" "\\|" ".*\\*/$" "\\)")) + diff --git a/scala-mode/scala-mode-feature-electric.el b/scala-mode/scala-mode-feature-electric.el new file mode 100644 index 0000000..838b2de --- /dev/null +++ b/scala-mode/scala-mode-feature-electric.el @@ -0,0 +1,181 @@ +;;; -*-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 to fit into the scala mode +;; Based on ruby-electric by Dee Zsombor . +;; Keywords: scala languages oop +;; $Id: scala-mode-feature-electric.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-feature-speedbar.el b/scala-mode/scala-mode-feature-speedbar.el new file mode 100644 index 0000000..0db0cbc --- /dev/null +++ b/scala-mode/scala-mode-feature-speedbar.el @@ -0,0 +1,90 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-feature-speedbar.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-feature-speedbar.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-feature-tags.el b/scala-mode/scala-mode-feature-tags.el new file mode 100644 index 0000000..3f3ff10 --- /dev/null +++ b/scala-mode/scala-mode-feature-tags.el @@ -0,0 +1,175 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-feature-tags.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-feature-tags.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-feature.el b/scala-mode/scala-mode-feature.el new file mode 100644 index 0000000..e825719 --- /dev/null +++ b/scala-mode/scala-mode-feature.el @@ -0,0 +1,70 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-feature.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-feature.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-fontlock.el b/scala-mode/scala-mode-fontlock.el new file mode 100644 index 0000000..99466b4 --- /dev/null +++ b/scala-mode/scala-mode-fontlock.el @@ -0,0 +1,210 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-fontlock.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-fontlock.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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-fontlock) + +(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)) + (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 + `(;; 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 "\\\\s *\\(" scala-ident-re "\\)") + (1 font-lock-type-face nil)) + + ;; variables + ("\\" + (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 *\\" + "\\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))) + )) + + +(defvar scala-font-lock-syntactic-keywords + `((,scala-char-re (0 "\"" t nil)) + (scala-search-special-identifier-forward (0 "w" nil nil)))) + + + diff --git a/scala-mode/scala-mode-indent.el b/scala-mode/scala-mode-indent.el new file mode 100644 index 0000000..9ca7169 --- /dev/null +++ b/scala-mode/scala-mode-indent.el @@ -0,0 +1,229 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-indent.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-indent.el 17339 2009-03-20 09:15:21Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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-indent) + +(defcustom scala-mode-indent:step 2 + "Indentation step." + :type 'integer + :group 'scala) + + +(defun scala-parse-partial-sexp () + (parse-partial-sexp (point-min) (point))) + +(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))) + +(defun scala-in-single-line-comment-p () + "Return t iff the point is inside a single line comment." + (let + (begin + end + subst + match) + (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))))) + +(defun scala-indentation () + "Return the suggested indentation for the current line." + (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)) + (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. + (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)))) + +(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))) diff --git a/scala-mode/scala-mode-inf.el b/scala-mode/scala-mode-inf.el new file mode 100644 index 0000000..d7cc473 --- /dev/null +++ b/scala-mode/scala-mode-inf.el @@ -0,0 +1,202 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-inf.el - Interaction with a Scala interpreter. + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-inf.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-lib.el b/scala-mode/scala-mode-lib.el new file mode 100644 index 0000000..2b02827 --- /dev/null +++ b/scala-mode/scala-mode-lib.el @@ -0,0 +1,115 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-lib.el - Libraries and macroes used by the scala mode. + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-lib.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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-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 () + (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"))) + + +(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)) diff --git a/scala-mode/scala-mode-navigation.el b/scala-mode/scala-mode-navigation.el new file mode 100644 index 0000000..84be0ee --- /dev/null +++ b/scala-mode/scala-mode-navigation.el @@ -0,0 +1,194 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-navigation.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-navigation.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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 "\\" + (forward-word 1) (scala-forward-spaces)) + (scala-forward-simple-type) + (while (scala-when-looking-at "\\s *\\\\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/scala-mode-ui.el b/scala-mode/scala-mode-ui.el new file mode 100644 index 0000000..e4984a8 --- /dev/null +++ b/scala-mode/scala-mode-ui.el @@ -0,0 +1,160 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-ui.el - Menu entries and keyboard shortcuts for scala mode + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-ui.el 17070 2009-02-10 08:51:50Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode-variables.el b/scala-mode/scala-mode-variables.el new file mode 100644 index 0000000..0e83547 --- /dev/null +++ b/scala-mode/scala-mode-variables.el @@ -0,0 +1,56 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode-feature.el - + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode-variables.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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/scala-mode.el b/scala-mode/scala-mode.el new file mode 100644 index 0000000..662c321 --- /dev/null +++ b/scala-mode/scala-mode.el @@ -0,0 +1,208 @@ +;;; -*-Emacs-Lisp-*- +;;; scala-mode.el - Major mode for editing Scala code. + +;; Copyright (C) 2009 Scala Dev Team at EPFL +;; Authors: See AUTHORS file +;; Keywords: scala languages oop +;; $Id: scala-mode.el 17069 2009-02-10 08:30:51Z nielsen $ + +;;; License + +;; SCALA LICENSE +;; +;; Copyright (c) 2002-2009 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) + +(require 'cl) + +(require 'scala-mode-constants) +(require 'scala-mode-variables) +(require 'scala-mode-lib) +(require 'scala-mode-navigation) +(require 'scala-mode-indent) +(require 'scala-mode-fontlock) +(require 'scala-mode-ui) +(require 'scala-mode-feature) + +;;; Customization and Variables +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defgroup scala nil + "Mode for editing Scala code." + :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: 17069 $") +(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)) + + +(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'." + (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)) + + +;;; Mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;###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 + ) + + (use-local-map scala-mode-map) + (turn-on-font-lock) + (scala-mode-feature-install) + (if scala-mode-hook + (run-hooks 'scala-mode-hook))) + + + +