[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/scala-mode a8b0936 003/217: Working on syntax
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/scala-mode a8b0936 003/217: Working on syntax |
Date: |
Sun, 29 Aug 2021 11:30:32 -0400 (EDT) |
branch: elpa/scala-mode
commit a8b0936d466b499f0e20897e93c2a9236c3608d0
Author: Heikki Vesalainen <heikkivesalainen@yahoo.com>
Commit: Heikki Vesalainen <heikkivesalainen@yahoo.com>
Working on syntax
---
Example.scala | 58 +++++++-
Test.scala | 31 ++++
scala-mode-constants.el | 8 ++
scala-mode-fontlock.el | 28 ++++
scala-mode-indent.el | 13 ++
scala-mode-map.el | 26 ++++
scala-mode-syntax.el | 376 ++++++++++++++++++++++++++++++++++++++++++++++++
scala-mode.el | 97 +++++++++++++
8 files changed, 631 insertions(+), 6 deletions(-)
diff --git a/Example.scala b/Example.scala
index 7eb013c..3b312b6 100644
--- a/Example.scala
+++ b/Example.scala
@@ -12,14 +12,14 @@ Indenting happens relative to an indent anchor. Usually the
indent anchor is the
the declaration or expression is inside a parameter list, then the anchor is
inside the list.
*/
-def f(s: String <%,
- i: Int) =
+def f(s: String,
+ i: Int) =
s.take(i) // indented relative to 'def'
/* */ val x = foo(
zot, // indented relative to '/* */'
someThing
- map (x=a===> x.length) // indented relative to 'someThing'
+ map (x => x.length) // indented relative to 'someThing'
)
val x =
@@ -41,7 +41,7 @@ Any line not beginning with a declaration or expression start
reserved word (i.e
This rule does not apply in the following cases:
- if the previous lines was empty
- previous line was an annotation
-- previous statement ended with ';'
+- previous statement ended with ';,'
- the current line starts a body (of declaration or anonymous function)
- block or simple expression starts with an anonymous function (lambda)
declaration
*/
@@ -89,6 +89,11 @@ List("foo", "bar")
s.length
)
+List("foo") map (
+ s => // start lambda
+ s.length // run-on rule does not apply
+)
+
/*
1.3 Parameter lists
@@ -102,6 +107,7 @@ of a line, it will be indented to the same column as the
first paremeter groups
parentheses.
- A closing parantheses that is on its own line, will be indented to the same
column
with the indent anchor.
+- Rule does not apply, if the first parameter was a lambda expression
*/
class Foo(
@@ -181,12 +187,17 @@ val z = for { i <- 1 to 10,
}
/*
-1.7 If statements
+1.7 If and try statements
If statements will be indented acording to the following rules:
-- The the body of the 'if' or 'else if' statement is a simple expression (i.e.
not a block), then the next 'else if' or 'else' is aligned with the previous
'if' or 'else if',
+- If the the body of the 'if' or 'else if' statement is a simple expression
(i.e. not a block), then the next 'else if' or 'else' is aligned with the
previous 'if' or 'else if',
- otherwise 'else if' and 'else' is aligned with previous block close.
+
+Try statements will be indented acording to the following rules:
+- If the body of the 'try' is a simple expression (i.e. not a block), then the
next 'catch' is aligned with the previous try
+- otherwise 'catch' is aligned with previous block close.
+- Finally is aligned similarly
*/
val x = if (kissa)
@@ -204,6 +215,25 @@ val y = if (kissa) {
zot
}
+val a = try
+ foo()
+ catch {
+ case e => bar()
+ }
+
+val b = try {
+ foo()
+} catch {
+ case e => bar()
+} finally {
+ zot()
+}
+
+val c = try
+ zot()
+ finally
+ log("zotted")
+
/*
1.8 Block opening curly brackets on new line
@@ -232,3 +262,19 @@ class Foo
"hello"
}
}
+
+/*
+2. font-lock support
+*/
+
+/*
+2.1 Types
+*/
+
+val strings = Seq("""multi
+line"quote
+strings""", "normal strings", 'c')
+
+val `quoted id` = 1
+
+val symbol = 'Symbol
diff --git a/Test.scala b/Test.scala
new file mode 100644
index 0000000..5fb26be
--- /dev/null
+++ b/Test.scala
@@ -0,0 +1,31 @@
+/* fooo bar */
+
+"""foo""".r """bar""".r
+
+"""
+qasduote_asdasd a+_
+'f'
+""", val zot "fo\ro"
+
+__
+
+asdasd_dfasdf_>> _<<
+
+val x:[Type <% Foo] => '\u123c'
+val y = "foo a\"sdasd"
+" ", " ", "as\"dasd"
+`asdasd`> asdasdasd
+"asdasd
+
+"""asdasdasd
+asdasda
+asdasdasd
+asdasdasd"asda"
+asdasdasdasdasd asd""
+asdasd
+asdasdasdasdasd"""asdasdasd
+
+"""asdasd"""asasdasd
+
+"""asdasdasdasdasdlkjhasd
+asdasdkj"""
diff --git a/scala-mode-constants.el b/scala-mode-constants.el
new file mode 100644
index 0000000..2c7507d
--- /dev/null
+++ b/scala-mode-constants.el
@@ -0,0 +1,8 @@
+;;; scala-mode-constants.el - Major mode for editing scala, constants
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
+
+;;; Based on Scala Language Specification (SLS) Version 2.9
+
+(provide 'scala-mode-constants)
+
diff --git a/scala-mode-fontlock.el b/scala-mode-fontlock.el
new file mode 100644
index 0000000..31f64ee
--- /dev/null
+++ b/scala-mode-fontlock.el
@@ -0,0 +1,28 @@
+;;; scala-mode-fontlock.el - Major mode for editing scala, font-lock
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
+
+(provide 'scala-mode-fontlock)
+
+(require 'scala-mode-syntax)
+(require 'scala-mode-constants)
+
+(defun scala-font-lock:mark-symbol (limit)
+ (if (re-search-forward scala-syntax:reserved-symbols-re limit t)
+ (goto-char (match-end 2)) ;; step back to the match (re matches futher)
+ nil))
+
+(defun scala-font-lock:mark-underscore (limit)
+ (if (re-search-forward scala-syntax:reserved-symbol-underscore-re limit t)
+ (goto-char (match-end 2)) ;; step back to the match (re matches futher)
+ nil))
+
+(defvar scala-font-lock:keywords
+ `(;; keywords
+ (,scala-syntax:keywords-re 0 font-lock-keyword-face)
+
+ ;; symbols
+ (scala-font-lock:mark-symbol 2 font-lock-keyword-face)
+ (scala-font-lock:mark-underscore 2 font-lock-keyword-face)
+
+))
diff --git a/scala-mode-indent.el b/scala-mode-indent.el
new file mode 100644
index 0000000..b10356e
--- /dev/null
+++ b/scala-mode-indent.el
@@ -0,0 +1,13 @@
+;;; scala-mode.el - Major mode for editing scala, indenting
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
+
+(provide 'scala-mode-indent)
+
+(defun scala-goto-indent-anhor ()
+ "moves back to the point whose column will be used as
+the anchor relative to which indenting is calculated."
+ (interactive)
+
+)
+
diff --git a/scala-mode-map.el b/scala-mode-map.el
new file mode 100644
index 0000000..9ad1758
--- /dev/null
+++ b/scala-mode-map.el
@@ -0,0 +1,26 @@
+;;; scala-mode-map.el - Major mode for editing scala, keyboard map
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
+
+(provide 'scala-mode-map)
+
+(defmacro scala-mode-map:define-keys (key-map key-funcs)
+ (cons 'progn (mapcar
+ #'(lambda (key-func)
+ `(define-key ,key-map ,(car key-func) ,(cadr key-func)))
+ key-funcs)))
+
+(defvar scala-mode-map nil
+ "Local key map used for scala mode")
+
+(when (not scala-mode-map)
+ (let ((keymap (make-sparse-keymap)))
+ (scala-mode-map:define-keys
+ keymap
+ (([backspace] 'backward-delete-char-untabify)
+ ;; ("\r" 'scala-newline)
+ ([(control c)(control c)] 'comment-region)
+ ;; ("}" 'scala-electric-brace)
+ ))
+ (setq scala-mode-map keymap)))
+
diff --git a/scala-mode-syntax.el b/scala-mode-syntax.el
new file mode 100644
index 0000000..84c3e10
--- /dev/null
+++ b/scala-mode-syntax.el
@@ -0,0 +1,376 @@
+;;;; scala-mode-syntax.el - Major mode for editing scala, syntax
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
+
+;;; Based on Scala Language Specification (SLS) Version 2.9
+
+(provide 'scala-mode-syntax)
+
+(require 'scala-mode-constants)
+
+;;;; Scala syntax regular expressions
+;;; Based on the Scala language specification 2.9. Note: order is not
+;;; the same as in the document, as here things are declared before
+;;; used.
+
+;;; A note on naming. Things that end with '-re' are regular
+;;; expressions. Things that end with '-group' are regular expression
+;;; character groups without the enclosing [], i.e. they are not
+;;; regular expressions, but can be used in declaring one.
+
+;; single letter matching groups (Chapter 1)
+(defconst scala-syntax:hexDigit-group "0-9A-Fa-f")
+(defconst scala-syntax:UnicodeEscape-re (concat "\\\\u["
scala-syntax:hexDigit-group "]\\{4\\}"))
+
+(defconst scala-syntax:upper-group "_[:upper:]\\$") ;; missing _ to make ids
work
+(defconst scala-syntax:upperAndUnderscore-group (concat "_"
scala-syntax:upper-group ))
+(defconst scala-syntax:lower-group "[:lower:]")
+(defconst scala-syntax:letter-group (concat scala-syntax:lower-group
scala-syntax:upper-group)) ;; TODO: add Lt, Lo, Nl
+(defconst scala-syntax:digit-group "0-9")
+(defconst scala-syntax:opchar-group "!#%&*+/:<=>?@\\\\\\^|~\\-") ;; TODO: Sm,
So
+
+;; Integer Literal (Chapter 1.3.1)
+(defconst scala-syntax:nonZeroDigit-group "1-9")
+(defconst scala-syntax:octalDigit-group "0-7")
+(defconst scala-syntax:decimalNumeral-re
+ (concat "0"
+ "\\|[" scala-syntax:nonZeroDigit-group "][" scala-syntax:digit-group
"]*"))
+(defconst scala-syntax:hexNumeral-re (concat "0x[" scala-syntax:hexDigit-group
"]+"))
+(defconst scala-syntax:octalNumeral-re (concat "0["
scala-syntax:octalDigit-group "]+"))
+(defconst scala-syntax:integerLiteral-re (concat "-?" ;; added from definition
of literal
+ "\\(" scala-syntax:decimalNumeral-re
+ "\\|" scala-syntax:hexNumeral-re
+ "\\|" scala-syntax:octalNumeral-re
+ "\\)[Ll]?"))
+
+;; Floating Point Literal (Chapter 1.3.2)
+(defconst scala-syntax:exponentPart-re (concat "\\([eE][+-]?["
scala-syntax:digit-group "]+\\)"))
+(defconst scala-syntax:floatType-re "[fFdD]")
+(defconst scala-syntax:floatingPointLiteral-re
+ (concat "-?" ;; added from definition of literal
+ "\\([" scala-syntax:digit-group "]+\\.[" scala-syntax:digit-group
"]*"
+ scala-syntax:exponentPart-re "?" scala-syntax:floatType-re "?"
+ "\\|" "\\.[" scala-syntax:digit-group "]+"
+ scala-syntax:exponentPart-re "?" scala-syntax:floatType-re "?"
+ "\\|" "[" scala-syntax:digit-group "]+" scala-syntax:exponentPart-re
+ "\\|" "[" scala-syntax:digit-group "]+" scala-syntax:floatType-re
"\\)"))
+
+;; Boolean Literals (Chapter 1.3.3)
+(defconst scala-syntax:booleanLiteral-re "true|false")
+
+;; Escape Sequences (Chapter 1.3.6)
+(defconst scala-syntax:escapeSequence-re "\\\\['btnfr\"\\\\]")
+
+;; Character Literals (Chapter 1.3.4)
+(defconst scala-syntax:characterLiteral-re
+ (concat "\\('\\)\\(" "[^\\\\]" ;; should be just printable char, but this is
faster
+ "\\|" scala-syntax:escapeSequence-re
+ "\\|" scala-syntax:UnicodeEscape-re "\\)\\('\\)"))
+
+;; String Literals (Chapter 1.3.5)
+(defconst scala-syntax:stringElement-re
+ (concat "\\(" "[^\n\"\\\\\]"
+ "\\|" scala-syntax:escapeSequence-re
+ "\\|" scala-syntax:UnicodeEscape-re "\\)"))
+(defconst scala-syntax:oneLineStringLiteral-re (concat "\\(\"\\)"
scala-syntax:stringElement-re "*\\(\"\\)"))
+(defconst scala-syntax:multiLineStringLiteral-re
+ "\\(\"\\)\\(\"\"\\(\"?\"?[^\"]\\)*\"\"+\\)\\(\"\\)")
+(defconst scala-syntax:stringLiteral-re
+ (concat "\\(" scala-syntax:multiLineStringLiteral-re
+ "\\|" scala-syntax:oneLineStringLiteral-re "\\)" ))
+
+;; Identifiers (Chapter 1.1)
+(defconst scala-syntax:op-re (concat "[" scala-syntax:opchar-group "]+"))
+(defconst scala-syntax:idrest-re
+ ;; Eagerness of regexp causes problems with _. The following is a workaround,
+ ;; but the resulting regexp matches only what SLS demands.
+ (concat "\\(" "[_]??" "[" scala-syntax:letter-group scala-syntax:digit-group
"]+" "\\)*"
+ "\\(" "_+" scala-syntax:op-re "\\|" "_" "\\)?"))
+(defconst scala-syntax:varid-re (concat "[" scala-syntax:lower-group "]"
scala-syntax:idrest-re))
+(defconst scala-syntax:capitalid-re (concat "["
scala-syntax:upperAndUnderscore-group "]" scala-syntax:idrest-re))
+(defconst scala-syntax:plainid-re (concat "\\(" scala-syntax:capitalid-re
+ "\\|" scala-syntax:varid-re
+ "\\|" scala-syntax:op-re "\\)"))
+;; stringlit is referred to, but not defined Scala Language Specification 2.9
+(defconst scala-syntax:stringlit-re (concat scala-syntax:stringElement-re
"*?"))
+(defconst scala-syntax:quotedid-re (concat "`" scala-syntax:stringlit-re "`"))
+(defconst scala-syntax:id-re (concat "\\(" scala-syntax:plainid-re
+ "\\|" scala-syntax:quotedid-re "\\)"))
+
+;; Symbol literals (Chapter 1.3.7)
+(defconst scala-syntax:symbolLiteral-re
+ ;; must end with non-' to not conflict with scala-syntax:characterLiteral-re
+ (concat "'" scala-syntax:plainid-re "\\([^']\\|$\\)"))
+
+;; Literals (Chapter 1.3)
+(defconst scala-syntax:literal-re
+ (concat "\\(" scala-syntax:integerLiteral-re
+ "\\|" scala-syntax:floatingPointLiteral-re
+ "\\|" scala-syntax:booleanLiteral-re
+ "\\|" scala-syntax:characterLiteral-re
+ "\\|" scala-syntax:stringLiteral-re
+ "\\|" scala-syntax:symbolLiteral-re
+ "\\|" "null" "\\)"))
+
+;; Paths (Chapter 3.1)
+(defconst scala-syntax:classQualifier-re (concat "\\[" scala-syntax:id-re
"\\]"))
+(defconst scala-syntax:stableId-re
+ (concat "\\(\\(" scala-syntax:id-re
+ "\\|" "this"
+ "\\|" "super" scala-syntax:classQualifier-re "\\)\\.\\)*"
+ scala-syntax:id-re))
+(defconst scala-syntax:path-re
+ (concat "\\(" scala-syntax:stableId-re
+ "\\|" "\\(" scala-syntax:id-re "\\." "\\)?" "this" "\\)"))
+
+
+;;;
+;;; Other regular expressions
+;;;
+
+(defconst scala-syntax:empty-line-re
+ "^\\s *$")
+
+(defconst scala-syntax:keywords-re
+ (regexp-opt '("abstract" "case" "catch" "class" "def"
+ "do" "else" "extends" "false" "final"
+ "finally" "for" "forSome" "if" "implicit"
+ "import" "lazy" "match" "new" "null"
+ "object" "override" "package" "private" "protected"
+ "return" "sealed" "super" "this" "throw"
+ "trait" "try" "true" "type" "val"
+ "var" "while" "with" "yield") 'words))
+
+
+;; false, true, null, super, this are neither
+
+(defconst scala-syntax:after-reserved-symbol-underscore-re
+ ;; what can be after reserved symbol _ (if there is something else, it
+ ;; will be upper case letter per SLS)
+ (concat "$\\|[^" scala-syntax:upper-group scala-syntax:lower-group
scala-syntax:digit-group "]"))
+
+(defconst scala-syntax:reserved-symbol-underscore-re
+ ;; reserved symbol _
+ (concat "\\(^\\|[^" scala-syntax:upper-group scala-syntax:lower-group
scala-syntax:digit-group "]\\)"
+ "\\(_\\)"
+ "\\($\\|[^" scala-syntax:upper-group scala-syntax:lower-group
scala-syntax:digit-group "]\\)"))
+
+(defconst scala-syntax:reserved-symbols-re
+ ;; reserved symbols and XML starts ('<!' and '<?')
+ (concat "\\(^\\|[^" scala-syntax:opchar-group "]\\)"
+ "\\([:=#@\u21D2\u2190]\\|=>\\|<[:%!?\\-]\\|>:\\)"
+ "\\($\\|[^" scala-syntax:opchar-group "]\\)"))
+
+(defconst scala-syntax:reserved-re
+ (concat scala-syntax:keywords-re "\\|" scala-syntax:reserved-symbols-re
"\\|" scala-syntax:reserved-symbol-underscore-re))
+
+(defconst scala-syntax:mustNotTerminate-keywords-re
+ "Keywords which cannot end a expression and are infact a sign of run-on."
+ (regexp-opt '("catch", "else", "extends", "finally",
+ "forSome", "match", "with", "yield") 'words))
+
+(defconst scala-syntax:mustNotTerminate-re
+ "All keywords and symbols that cannot terminate a expression
+and are infact a sign of run-on, except for @, which may start
+an expression with annotation."
+ (concat "\\(" scala-syntax:mustNotTerminate-keywords-re
+ "\\|" scala-syntax:reserved-symbols-re "\\)"))
+
+(defconst scala-syntax:mustTerminate-re
+ "Symbols that must terminate an expression, i.e the following expression
+cannot be a run-on. This includes only , and ; and the empty line"
+ (concat "\\([,;]|" scala-syntax:empty-line-re "\\)"))
+
+(defconst scala-syntax:mustNotContinue-re
+ "Keywords that begin an expression, i.e they cannot be run-on to the
+previous the line even if there is no semi in between."
+ ;; 'case' and 'while' are unclear. 'case' might belong to 'case class'
+ ;; while 'while' might belong to a 'do..while'
+ (regexp-opt '("abstract", "class", "def", "do", "final",
+ "for", "if", "implicit", "import", "lazy",
+ "new", "object", "override", "package", "private",
+ "protected", "return", "sealed", "throw",
+ "trait", "try", "type", "val", "var") 'words))
+
+(defconst scala-syntax:double-arrow-re
+ "=>\\|\u21D2")
+
+(defconst scala-syntax:multiLineStringLiteral-start-re
+ "\\(\"\\)\"\"")
+
+(defconst scala-syntax:multiLineStringLiteral-end-re
+ "\"\"+\\(\"\\)")
+
+(defun scala-syntax:find-reserved-symbols ()
+ (interactive)
+ (re-search-forward scala-syntax:reserved-symbols-re nil t))
+
+
+;;;; Character syntax table and related syntax-propertize functions
+;;; The syntax table relies havily on the syntax-propertize-functions being
+;;; run. Hence this syntax requires at least emacs 24, which introduced
+;;; this new facility.
+
+(defvar scala-syntax:syntax-table nil
+ "Syntax table used in `scala-mode' buffers.")
+(when (not scala-syntax:syntax-table)
+ (let ((syntab (make-syntax-table)))
+ ;; 1. start by reseting the syntax table: only (){}[] are
+ ;; parentheses, so all others marked as parentheses in the parent
+ ;; table must be marked as symbols, nothing is a punctuation
+ ;; unless otherwise stated
+ (map-char-table
+ #'(lambda (key value)
+ (when (or (= (syntax-class value) 4) ; open
+ (= (syntax-class value) 5) ; close
+ (= (syntax-class value) 1)) ; punctuation
+ (modify-syntax-entry key "_" syntab)))
+ (char-table-parent syntab))
+
+ ;; Below 'space', everything is either illegal or whitespace.
+ ;; Consider as whitespace, unless otherwise stated below.
+ (modify-syntax-entry '(0 . 32) " " syntab)
+
+ ;; The scala parentheses
+ (modify-syntax-entry ?\( "()" syntab)
+ (modify-syntax-entry ?\[ "(]" syntab)
+ (modify-syntax-entry ?\{ "(}" syntab)
+ (modify-syntax-entry ?\) ")(" syntab)
+ (modify-syntax-entry ?\] ")[" syntab)
+ (modify-syntax-entry ?\} "){" syntab)
+
+ ;; _ is upper-case letter, but will be modified to be punctuation
+ ;; when in reserved symbol position by syntax-propertize-function
+ (modify-syntax-entry ?\_ "w" syntab)
+
+ ;; by default all opchars are punctuation, but they will be
+ ;; modified by syntax-propertize-function to be symbol
+ ;; constituents when a part of varid or capitalid
+ (dolist (char (mapcar 'identity "#%:<=>@!&*+-/?\\^|~\u21D2\u2190")) ;;
TODO: Sm, So
+ (modify-syntax-entry char "." syntab))
+
+ ;; what can I say? It's the escape char.
+ (modify-syntax-entry ?\\ "." syntab)
+
+ ;; scala strings cannot span lines, so we mark
+ ;; " as punctuation, but do the real stuff
+ ;; in syntax-propertize-function for properly
+ ;; formatted strings.
+ (modify-syntax-entry ?\" "." syntab)
+
+ ;; backquote is given paired delimiter syntax so that
+ ;; quoted ids are parsed as one sexp. Fontification
+ ;; is done separately.
+ (modify-syntax-entry ?\` "$" syntab)
+
+ ;; ' is considered an expression prefix, since it can
+ ;; both start a Symbol and is a char quote. It
+ ;; will be given string syntax by syntax-propertize-function
+ ;; for properly formatted char literals.
+ (modify-syntax-entry ?\' "'" syntab)
+
+ ;; punctuation as specified by SLS
+ (modify-syntax-entry ?\. "." syntab)
+ (modify-syntax-entry ?\; "." syntab)
+ (modify-syntax-entry ?\, "." syntab)
+
+ ;; comments
+ ;; the `n' means that comments can be nested
+ (modify-syntax-entry ?\/ ". 124b" syntab)
+ (modify-syntax-entry ?\* ". 23n" syntab)
+ (modify-syntax-entry ?\n "> b" syntab)
+ (modify-syntax-entry ?\r "> b" syntab)
+
+ (setq scala-syntax:syntax-table syntab)))
+
+(defun scala-syntax:propertize-extend-region (start end)
+ "See syntax-propertize-extend-region-functions"
+ ;; nothing yet
+ nil)
+
+(defmacro scala-syntax:put-syntax-table-property (match-group value)
+ "Add 'syntax-table entry 'value' to the region marked by the
+match-group 'match-group'"
+ `(put-text-property (match-beginning ,match-group)
+ (match-end ,match-group)
+ 'syntax-table
+ ,value))
+
+(defun scala-syntax:propertize-characterLiterals (start end)
+ "Mark start and end of character literals as syntax class
+7 (string quotes). Only valid character literals will be marked."
+ (save-excursion
+ (goto-char start)
+ (while (re-search-forward scala-syntax:characterLiteral-re end t)
+ (scala-syntax:put-syntax-table-property 1 '(7 . nil))
+ (scala-syntax:put-syntax-table-property 3 '(7 . nil)))))
+
+(defun scala-syntax:propertize-stringLiterals (start end)
+ "Mark start and end of both one-line and multi-line string
+literals. One-line strings use syntax class 7 (string quotes),
+while multi-line strings are marked with 15 (generic string
+delimiter). Multi-line string literals are marked even if they
+are unbalanced. One-line string literals have to be balanced to
+get marked. This means invalid one-line strings will not be fontified."
+ (let* ((string-state (nth 3 (syntax-ppss start)))
+ (unbalanced-p (eq string-state t)))
+
+ (if (and string-state (not unbalanced-p))
+ ;; a normal string is open, let's de-propertize
+ (remove-text-properties start end '(syntax-table nil))
+ (save-excursion
+ (goto-char start)
+ ;; close the closing for the unbalanced multi-line literal
+ (when (and unbalanced-p
+ (re-search-forward
scala-syntax:multiLineStringLiteral-end-re end t))
+ (scala-syntax:put-syntax-table-property 1 '(15 . nil)))
+ ;; match any balanced one-line or multi-line literals
+ (catch 'break
+ (while (re-search-forward scala-syntax:stringLiteral-re end t)
+ (cond
+ ((match-beginning 2)
+ (scala-syntax:put-syntax-table-property 2 '(15 . nil))
+ (scala-syntax:put-syntax-table-property 5 '(15 . nil)))
+ ((or (match-end 7) ; group 7 is non-nil, ie. online string is not
empty
+ (= (match-end 8) (line-end-position)) ; empty string at line
end
+ (not (= (char-after (match-end 8)) ?\"))) ; no " after empty
string
+ (scala-syntax:put-syntax-table-property 6 '(7 . nil))
+ (scala-syntax:put-syntax-table-property 8 '(7 . nil)))
+ (t ;; backtrack and continue to next while loop
+ (goto-char (match-beginning 0))
+ (throw 'break nil)))))
+ ;; match any start of multi-line literals that are not yet balanced
+ (when (re-search-forward scala-syntax:multiLineStringLiteral-start-re
end t)
+ (scala-syntax:put-syntax-table-property 1 '(15 . nil)))))))
+
+(defun scala-syntax:propertize-underscore-and-idrest (start end)
+ "Mark all underscores (_) as punctuation (syntax 1) or upper
+case letter (syntax 2). Also mark opchars in idrest as symbol
+constituents (syntax 3)"
+ (save-excursion
+ (goto-char start)
+ (while (re-search-forward "_" end t)
+ (let ((match-beg (match-beginning 0))
+ (match-end (match-end 0)))
+ (put-text-property
+ match-beg match-end 'syntax-table
+ (if (= match-beg (line-beginning-position))
+ (if (looking-at scala-syntax:after-reserved-symbol-underscore-re)
+ '(1 . nil) ; punctuation
+ '(2 . nil)) ; word syntax
+ (save-excursion
+ (goto-char (1- match-beg))
+ (if (looking-at scala-syntax:reserved-symbol-underscore-re)
+ '(1 . nil) ; punctuation
+ ;; check for opchars that should be marked as symbol
constituents (3)
+ (goto-char match-end)
+ (when (looking-at scala-syntax:op-re)
+ (scala-syntax:put-syntax-table-property 0 '(3 . nil)))
+ '(2 . nil))))))))) ;; word syntax (2) for the '_'
+
+(defun scala-syntax:propertize (start end)
+ "See syntax-propertize-function"
+ (scala-syntax:propertize-characterLiterals start end)
+ (scala-syntax:propertize-stringLiterals start end)
+ (scala-syntax:propertize-underscore-and-idrest start end))
+
diff --git a/scala-mode.el b/scala-mode.el
new file mode 100644
index 0000000..5038b7b
--- /dev/null
+++ b/scala-mode.el
@@ -0,0 +1,97 @@
+;;; scala-mode.el - Major mode for editing scala
+;;; Copyright (c) 2012 Heikki Vesalainen
+;;; For information on the License, see the LICENSE file
+
+;;; Based on Scala Language Specification (SLS) Version 2.9
+
+(provide 'scala-mode)
+
+(require 'scala-mode-constants)
+(require 'scala-mode-syntax)
+(require 'scala-mode-fontlock)
+(require 'scala-mode-indent)
+(require 'scala-mode-map)
+
+;; Tested only for emacs 23
+(unless (<= 23 emacs-major-version)
+ (error
+ (format "The Scala mode has been tested only on Emacs version 23.x (and not
your Emacs version %s.%s)"
+ emacs-major-version emacs-minor-version)))
+
+;; Attach .scala files to the scala-mode
+(add-to-list 'auto-mode-alist '("\\.scala\\'" . scala-mode))
+(modify-coding-system-alist 'file "\\.scala\\'" 'utf-8)
+
+
+(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 ()
+;; "Major mode for editing scala code.
+
+;; When started, runs `scala-mode-hook'.
+
+;; \\{scala-mode-map}"
+;; (interactive)
+;; (kill-all-local-variables)
+;; (set-syntax-table scala-mode-syntax-table)
+
+;; (scala-mode:make-local-variables
+;; 'require-final-newline
+;; 'comment-start
+;; 'comment-end
+;; 'comment-start-line
+;; 'comment-column
+;; 'comment-multi-line)
+
+;;;###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-defaults
+ 'comment-start
+ 'comment-end
+ 'comment-start-skip
+ 'comment-column
+ 'comment-multi-line)
+
+ (add-hook 'syntax-propertize-extend-region-functions
+ 'scala-syntax:propertize-extend-region)
+ (setq
+ syntax-propertize-function 'scala-syntax:propertize
+ parse-sexp-lookup-properties t
+
+ ;; TODO: font-lock
+ font-lock-defaults '(scala-font-lock:keywords
+ nil)
+
+ ;; TODO: paragraph-start, paragraphs-separate,
paragraph-ignore-fill-prefix
+ ;; TODO: beginning-of-defun-function, end-of-defun-function
+
+ ;; comments
+ comment-start "// "
+ comment-end ""
+ comment-start-skip "\\(//+\\|/\\*+\\)\\s *"
+ comment-column 0
+ comment-multi-line t
+ ;; TODO: comment-indent-function
+ )
+ (use-local-map scala-mode-map)
+ (turn-on-font-lock)
+)
+
+
+
+
+
+
+
- [nongnu] branch elpa/scala-mode created (now 598cb68), ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 5ba0a78 005/217: run-on and list indent primitives, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode ca7308a 002/217: Initial commit with README and Example.scala outlining how it will work, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode a8b0936 003/217: Working on syntax,
ELPA Syncer <=
- [nongnu] elpa/scala-mode 6f1b748 001/217: Example.scala to show how we intend to indent, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 3413883 004/217: run-on-p, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode f0cc3d4 006/217: working on indent rules, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode f17fa95 007/217: approaching a functioning indent engine, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 4dbaa5f 010/217: picked some of Erik's fontlock magic for an interim solution, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 84e5c8a 013/217: regression fix, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode aebc5b0 017/217: Fixes #7: indenting of block lines when at last char of buffer, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode c3ea76f 009/217: fixed indenting of if body (and probably other things), ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode ba3c9ca 020/217: renamed README to README.md, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 9f74c7d 015/217: Partial fix to #5., ELPA Syncer, 2021/08/29