;;; scala-mode.el --- Major mode for editing Scala
;; Copyright (c) 2012 Heikki Vesalainen
;; Homepage: https://github.com/hvesalai/emacs-scala-mode
;; Keywords: languages
;; Package-Version: 0.23
;; Package-Requires: ()
;;; Commentary:
;;
;;; Code:
(require 'scala-mode-lib)
(require 'scala-mode-syntax)
(require 'scala-mode-paragraph)
(require 'scala-mode-indent)
(require 'scala-mode-fontlock)
(require 'scala-mode-map)
(require 'scala-mode-imenu)
(require 'scala-mode-prettify-symbols)
(defvar fixup-whitespace) ;; for compilation
(defvar delete-indentation) ;; for compilation
;; Tested only for emacs 24
(unless (<= 24 emacs-major-version)
(error
(format "The Scala mode has been tested only on Emacs version 24.2 (and not your Emacs version %s.%s)"
emacs-major-version emacs-minor-version)))
(defgroup scala nil
"A programming mode for the Scala language 2 and 3"
:group 'languages)
(defmacro scala-mode:make-local-variables (&rest quoted-names)
(cons 'progn (mapcar #'(lambda (quoted-name) `(make-local-variable ,quoted-name)) quoted-names)))
(defun scala-mode:find-tag ()
"Determine default tag to search for, based on text at point.
If there is no plausible default, return nil."
(let (from to)
(when (and (progn
;; Look at text around `point'.
(save-excursion
(if (< 0 (skip-chars-backward scala-syntax:opchar-group))
(if (= (char-before) ?_)
(skip-syntax-backward "w_"))
(skip-syntax-backward "w_"))
(setq from (point)))
(save-excursion
(skip-syntax-forward "w_.") (setq to (point)))
(save-excursion
(ignore-errors (scala-syntax:backward-sexp)) (setq from (max from (point))))
(save-excursion
(goto-char from)
(ignore-errors (scala-syntax:forward-sexp)) (setq to (min to (point))))
(> to from))
(save-excursion
(goto-char from)
(and (looking-at scala-syntax:id-re)
(not (looking-at scala-syntax:keywords-unsafe-re)))))
(buffer-substring-no-properties from to))))
(defun scala-mode:forward-sexp-function (&optional count)
(unless count (setq count 1))
(if (< count 0)
(dotimes (n (abs count))
(scala-syntax:backward-sexp))
(dotimes (n count)
(scala-syntax:forward-sexp))))
;;;###autoload
(defun scala-mode:set-scala-syntax-mode ()
"Sets the syntax-table and other related variables for the current buffer to those of scala-mode. Can be used to make some other major mode (such as sbt-mode) use scala syntax-table."
(set-syntax-table scala-syntax:syntax-table)
(scala-mode:make-local-variables
'syntax-propertize-function
'parse-sexp-lookup-properties
'forward-sexp-function)
(add-hook 'syntax-propertize-extend-region-functions
'scala-syntax:propertize-extend-region)
(setq syntax-propertize-function 'scala-syntax:propertize
parse-sexp-lookup-properties t
forward-sexp-function 'scala-mode:forward-sexp-function))
;;;###autoload
(defun scala-mode:goto-start-of-code ()
"Go to the start of the real code in the file: object, class or trait."
(interactive)
(let* ((case-fold-search nil))
(search-forward-regexp "\\([[:space:]]+\\|^\\)\\(class\\|object\\|trait\\)" nil t)
(move-beginning-of-line nil)))
;;;###autoload
(define-derived-mode scala-mode prog-mode "Scala"
"Major mode for editing scala code.
When started, runs `scala-mode-hook'.
\\{scala-mode-map}"
:syntax-table scala-syntax:syntax-table
; :group
; :abbrev
(scala-mode:make-local-variables
'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-regexp
'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-regexp "[ \t]*\\(//+[ \t]*\\)*"
adaptive-fill-first-line-regexp scala-paragraph:fill-first-line-re
comment-start "// "
comment-end ""
comment-start-skip "\\(//+\\|/\\*+\\)[ \t]*"
comment-column 0
comment-multi-line t
forward-sexp-function 'scala-mode:forward-sexp-function
find-tag-default-function 'scala-mode:find-tag
indent-line-function 'scala-indent:indent-line
fixup-whitespace 'scala-indent:fixup-whitespace
delete-indentation 'scala-indent:join-line
indent-tabs-mode nil
beginning-of-defun-function #'scala-syntax:beginning-of-definition
end-of-defun-function #'scala-syntax:end-of-definition
imenu-create-index-function #'scala-imenu:create-imenu-index)
(use-local-map scala-mode-map)
;; add indent functionality to some characters
(scala-mode-map:add-remove-indent-hook)
(scala-mode-map:add-self-insert-hooks))
;; Attach .scala files to the scala-mode
;;;###autoload
(progn
(add-to-list 'auto-mode-alist
'("\\.\\(scala\\|sbt\\|worksheet\\.sc\\)\\'" . scala-mode))
(modify-coding-system-alist 'file "\\.\\(scala\\|sbt\\|worksheet\\.sc\\)\\'" 'utf-8))
(provide 'scala-mode)
;;; scala-mode.el ends here