[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/scala-mode f0cc3d4 006/217: working on indent rules
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/scala-mode f0cc3d4 006/217: working on indent rules |
Date: |
Sun, 29 Aug 2021 11:30:33 -0400 (EDT) |
branch: elpa/scala-mode
commit f0cc3d409f866c3de6f7ffccb9b0d68487b4e1de
Author: Heikki Vesalainen <heikkivesalainen@yahoo.com>
Commit: Heikki Vesalainen <heikkivesalainen@yahoo.com>
working on indent rules
---
Example.scala | 31 +++++------
scala-mode-indent.el | 141 +++++++++++++++++++++++++++++++++++++++++++--------
scala-mode-map.el | 1 -
scala-mode-syntax.el | 14 +++--
scala-mode.el | 23 +++++----
5 files changed, 159 insertions(+), 51 deletions(-)
diff --git a/Example.scala b/Example.scala
index fb315c0..c1aa32a 100644
--- a/Example.scala
+++ b/Example.scala
@@ -19,7 +19,7 @@ def f(s: String,
/* */ val x = foo(
zot, // indented relative to '/* */'
someThing
- map (x => x.length) // indented relative to 'someThing'
+ map (x => x.length) // indented relative to 'someThing'
)
val x =
@@ -73,7 +73,7 @@ class Foo(
// body here
}
-trait Leijona( x: Int,
+trait Leijona( x: Int with Int,
y: Int )
extends Kissa // run-one line, acnhor is 'trait'
with Harja // ditto
@@ -85,9 +85,10 @@ def someThingReallyLong(having: String, aLot: Int,
ofParameters: Boolean):
}
List("foo", "bar")
- map ( s => // 'map' indented as run-on, 's =>' start lambda
- s.length
- )
+ map { s =>
+ s.length // 'map' indented as run-on, 's =>' start lambda
+ toString
+ }
List("foo") map (
s => // start lambda
@@ -115,8 +116,8 @@ class Foo( /* */
k: String
) // at indent anchor column
-def f( i: String, j: String,
- k: String) // indented acording to previous
+def f( /* */ i: String, j: String with Bar,
+ k: String) // indented acording to previous
val f = foo(kissa,
kala)
@@ -245,22 +246,22 @@ While not couraged, should the opening curly bracket of a
block be on a new line
specified return value and one step from anchor otherwise.
*/
-class Foo
-{
+class Foo {
def foo
{
- println(zot)
+ zot
+ foo
}
def bar =
- {
+ {
zot
- }
+ }
val zot =
- {
- "hello"
- }
+ {
+"hello"
+ }
}
/*
diff --git a/scala-mode-indent.el b/scala-mode-indent.el
index 64492c0..6bce7cd 100644
--- a/scala-mode-indent.el
+++ b/scala-mode-indent.el
@@ -4,8 +4,16 @@
(provide 'scala-mode-indent)
+(require 'scala-mode-syntax)
+(require 'scala-mode-lib)
+
+(defcustom scala-indent:step 2
+ "The number of spaces an indentation step should be. The actual
+indentation will be one or two steps depending on context."
+ :type 'integer
+ :group 'scala)
+
(defun scala-indent:run-on-p (&optional point)
- (interactive)
"Returns t if the current point (or point at 'point) is on a
line that is a run-on from a previous line."
(save-excursion
@@ -19,27 +27,34 @@ line that is a run-on from a previous line."
; (defconst scala-syntax:mustNotTerminate-re
; scala-syntax:reserved-symbols-unsafe-re
-(defun scala-indent:goto-run-on-beginning ()
+(defun scala-indent:goto-run-on-anchor (&optional point)
"Moves back to the point whose column will be used as the
-anchor relative to which indenting is calculated. If this row is
-not a run on, does nothing."
- (when (scala-indent:run-on-p)
+anchor relative to which indenting for currnet point (or point
+'point') is calculated. Returns the new point or nil if point is
+not on a run-on line."
+ (if (not (scala-indent:run-on-p point))
+ nil
+ (when point (goto-char point))
(scala-syntax:beginning-of-code-line)
- (let ((block-beg (or (nth 1 (syntax-ppss)) (point-min))))
+ (let ((block-beg (1+ (or (nth 1 (syntax-ppss)) (1- (point-min))))))
(while (and (scala-indent:run-on-p)
(> (point) block-beg))
- (if (scala-syntax:looking-back-token "\\s)" 1)
- (backward-list)
- (skip-syntax-backward "^)" (max block-beg (line-beginning-position
0))))))
- (unless (= (char-syntax (char-before)) ?\()
- (scala-syntax:beginning-of-code-line))))
+ ;; move back all parameter groups, if any
+ (scala-syntax:beginning-of-code-line)
+ (scala-syntax:skip-backward-ignorable)
+ (scala-syntax:backward-parameter-groups)))
+ (back-to-indentation)
+;;; (when (< (point) block-beg)
+;;; (goto-char block-beg)))
+ (point)))
(defun scala-indent:list-element-line-p (&optional point)
- "Returns t if the current point is in a list. A list is
-something that begins with '(' or '[', or 'for {'. A list element
-is preceded by ,"
+ "Returns t if the current point (or point 'point') is in a
+list. A list is something that begins with '(' or '[', or 'for
+{'. A list element is preceded by ,"
(save-excursion
;; first check that the previous line ended with ','
+ (when point (goto-char point))
(beginning-of-line)
(let ((list-beg (nth 1 (syntax-ppss))))
(if (not (and (scala-syntax:looking-back-token "," 1)
@@ -52,12 +67,13 @@ is preceded by ,"
(and (= (char-after list-beg) ?\{)
(scala-syntax:looking-back-token "for")))))))
-(defun scala-indent:goto-list-beginning ()
+(defun scala-indent:goto-list-anchor (&optional point)
"Moves back to the point whose column will be used to indent
-lists rows. If this row is not a list element, does nothing"
- (interactive)
- (when (scala-indent:list-element-line-p)
- (goto-char (1+ (nth 1 (syntax-ppss))))
+list rows at current point (or point 'point'). Returns the new
+point or nil if the point is not in a list element > 1."
+ (if (not (scala-indent:list-element-line-p point))
+ nil
+ (goto-char (1+ (nth 1 (syntax-ppss point))))
(let ((block-beg (point)))
(forward-comment (buffer-size))
(if (= (line-number-at-pos (point))
@@ -66,5 +82,90 @@ lists rows. If this row is not a list element, does nothing"
(progn (goto-char block-beg)
(skip-syntax-forward " "))
;; on different line
- (back-to-indentation)))))
+ (back-to-indentation))
+ (point))))
+
+(defun scala-indent:body-p (&optional point)
+ "Return t if current point (or point 'point) is on a line
+that follows = or => (or it's unicode equivalent)"
+ (save-excursion
+ (when point (goto-char point))
+ (beginning-of-line)
+ (scala-syntax:looking-back-token scala-syntax:body-start-re 2)))
+
+(defun scala-indent:goto-body-anchor (&optional point)
+ (if (not (scala-indent:body-p point))
+ nil
+ (when point (goto-char point))
+ (beginning-of-line)
+ (goto-char (or (nth 1 (syntax-ppss point)) (point-min)))
+ (beginning-of-line)
+ (point)))
+
+(defun scala-indent:goto-block-anchor (&optional point)
+ "Moves back to the point whose column will be used as the
+anchor for calculating block indent for current point (or point
+'point'). Returns point or nil, if not inside a block."
+ (let ((block-beg (nth 1 (syntax-ppss point))))
+ (if (not block-beg)
+ nil
+ (scala-indent:goto-run-on-anchor block-beg))))
+
+(defun scala-indent:parentheses-line-p (&optional point)
+ ""
+ (save-excursion
+ (when point (goto-char point))
+ (scala-syntax:beginning-of-code-line)
+ (= (char-syntax (char-after)) ?\()))
+
+(defun scala-indent:parentheses-anchor (&optional point)
+ "Moves back to the point whose column will be used as the
+anchor for calculating opening parenthesis indent for the current
+point (or point 'point'). Returns point or nil, if line does not
+start with opening parenthesis."
+ (if (not (scala-indent:parentheses-line-p point))
+ nil
+ (scala-indent:goto-run-on-anchor point)))
+
+(defun scala-indent:apply-indent-rules (rule-indents &optional point)
+ "Evaluates each rule, until one returns non-nil value. Returns
+the sum of the value and the respective indent step, or nil if
+nothing was applied."
+ (if (not rule-indents)
+ nil
+ (save-excursion
+ (let* ((rule-indent (car rule-indents))
+ (rule (car rule-indent))
+ (indent (cadr rule-indent))
+ (anchor (funcall rule point)))
+ (if anchor
+ (+ (current-column) (eval indent))
+ (scala-indent:apply-indent-rules (cdr rule-indents)))))))
+
+(defun scala-indent:calculate-indent-for-line (&optional point)
+ "Calculate the appropriate indent for the current point or the
+point 'point'"
+ (or (scala-indent:apply-indent-rules
+ `((scala-indent:parentheses-anchor 0)
+ (scala-indent:goto-run-on-anchor (* 2 scala-indent:step))
+ (scala-indent:goto-list-anchor 0)
+ (scala-indent:goto-body-anchor scala-indent:step)
+ (scala-indent:goto-block-anchor scala-indent:step))
+ point)
+ 0))
+
+(defun scala-indent:indent-line-to (column)
+ "Indent the line to column and move cursor to the indent
+column, if it was at the left margin."
+ (if (<= (current-column) (current-indentation))
+ (indent-line-to column)
+ (save-excursion (indent-line-to column))))
+(defun scala-indent:indent-line ()
+ "Indents the current line."
+ (interactive)
+ ;; TODO: do nothing if inside string or comment
+ (let ((indent (scala-indent:calculate-indent-for-line)))
+ (when indent
+ (scala-indent:indent-line-to indent))))
+
diff --git a/scala-mode-map.el b/scala-mode-map.el
index 1c620af..9ad1758 100644
--- a/scala-mode-map.el
+++ b/scala-mode-map.el
@@ -18,7 +18,6 @@
(scala-mode-map:define-keys
keymap
(([backspace] 'backward-delete-char-untabify)
- ([(control c)(control r)] 'scala-indent:goto-list-beginning) ; TODO
remove
;; ("\r" 'scala-newline)
([(control c)(control c)] 'comment-region)
;; ("}" 'scala-electric-brace)
diff --git a/scala-mode-syntax.el b/scala-mode-syntax.el
index 6c77a7e..e04f9df 100644
--- a/scala-mode-syntax.el
+++ b/scala-mode-syntax.el
@@ -216,8 +216,8 @@ and the empty line")
expression, i.e they cannot be run-on to the previous line even
if there is no semi in between.")
-(defconst scala-syntax:double-arrow-re
- "=>\\|\u21D2")
+(defconst scala-syntax:body-start-re
+ "=>?\\|\u21D2")
(defconst scala-syntax:multiLineStringLiteral-start-re
"\\(\"\\)\"\"")
@@ -274,10 +274,10 @@ if there is no semi in between.")
;; 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
+ (dolist (char (mapcar 'identity "!#%&*+/:<=>?@^|~-\u21D2\u2190")) ;; TODO:
Sm, So
(modify-syntax-entry char "." syntab))
- ;; what can I say? It's the escape char.
+ ;; for clarity, the \ is alone here and not in the string above
(modify-syntax-entry ?\\ "." syntab)
;; scala strings cannot span lines, so we mark
@@ -413,6 +413,7 @@ symbol constituents (syntax 3)"
the line, if the line is empty"
(let ((eol (line-end-position)))
(beginning-of-line)
+ ;; TODO: check if we are inside a comment and come out of it
(forward-comment (buffer-size))
(if (> (point) eol)
eol
@@ -453,3 +454,8 @@ empty line. Expects to be outside of comment."
(if (= (point) end)
nil
(if (looking-at re) (point) nil)))))
+
+(defun scala-syntax:backward-parameter-groups ()
+ "Move back over all parameter groups to the start of the first one."
+ (while (scala-syntax:looking-back-token "\\s)" 1)
+ (backward-list)))
diff --git a/scala-mode.el b/scala-mode.el
index 5038b7b..2dc9b18 100644
--- a/scala-mode.el
+++ b/scala-mode.el
@@ -18,10 +18,9 @@
(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)
-
+(defgroup scala nil
+ "A programming mode for the Scala language 2.9"
+ :group 'languages)
(defmacro scala-mode:make-local-variables (&rest quoted-names)
(cons 'progn (mapcar #'(lambda (quoted-name) `(make-local-variable
,quoted-name)) quoted-names)))
@@ -62,7 +61,9 @@ When started, runs `scala-mode-hook'.
'comment-end
'comment-start-skip
'comment-column
- 'comment-multi-line)
+ 'comment-multi-line
+ 'indent-line-function
+ 'indent-tabs-mode)
(add-hook 'syntax-propertize-extend-region-functions
'scala-syntax:propertize-extend-region)
@@ -84,14 +85,14 @@ When started, runs `scala-mode-hook'.
comment-column 0
comment-multi-line t
;; TODO: comment-indent-function
+
+ indent-line-function 'scala-indent:indent-line
+ indent-tabs-mode nil
)
(use-local-map scala-mode-map)
(turn-on-font-lock)
)
-
-
-
-
-
-
+;; Attach .scala files to the scala-mode
+(add-to-list 'auto-mode-alist '("\\.scala\\'" . scala-mode))
+(modify-coding-system-alist 'file "\\.scala\\'" 'utf-8)
- [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, 2021/08/29
- [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 <=
- [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
- [nongnu] elpa/scala-mode 84d9c10 011/217: highlight string escapes, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 150e3d2 012/217: updated README with some TODOs, ELPA Syncer, 2021/08/29
- [nongnu] elpa/scala-mode 64c496a 016/217: Fixed #4: numbers in ids, ELPA Syncer, 2021/08/29