From ad122e464e4081465ed4478fba5214ac5fe852e0 Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Fri, 31 Mar 2023 19:47:12 -0700 Subject: [PATCH 1/7] fix typo in function name --- scala-mode-indent.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index 0df2ba5..1612720 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -653,7 +653,7 @@ Returns point or (point-min) if not inside a block." (setq last-indentation (current-indentation)) (while (looking-at-p "\\.") (backward-char)) ;; ")." is a funny case where we actually do want to be on the dot - (if (looking-at-p ")") (forwar-char)) + (if (looking-at-p ")") (forward-char)) (scala-syntax:backward-sexp-forcing))) (let* ((x (or (scala-indent:skip-back-over-modifiers (point) stack) (list (point) stack))) From 56d1f77e9047cc767d105ffca28d5ec3e326648c Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Fri, 31 Mar 2023 19:47:34 -0700 Subject: [PATCH 2/7] indent after declarations --- scala-mode-indent.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index 1612720..694089d 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -537,7 +537,7 @@ Returns point or (point-min) if not inside a block." (`(decl else) -2) (`(decl . ,_) 2) ;; decl-lhs - (`(decl-lhs decl . ,_) 0) + (`(decl-lhs decl . ,_) 2) (`(decl-lhs dot-chain) 4) (`(dot-chain dot-chain) 0) (`(decl-lhs for-comp) 0) From 5323a097a7fa06d08f525dc76c27c16cdf516826 Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Fri, 31 Mar 2023 19:47:56 -0700 Subject: [PATCH 3/7] do not push nil into the analysis stack --- scala-mode-indent.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index 694089d..553bb80 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -756,7 +756,10 @@ certain amount of incorrect or in-progress syntactic forms." (setq point (nth 2 x)) t) (setq analysis (scala-indent:analyze-context point stack)) - (setq syntax-elem (cons (nth 0 analysis) syntax-elem)) + (setq syntax-elem + (if (nth 0 analysis) + (cons (nth 0 analysis) syntax-elem) + syntax-elem)) (setq ctxt-line (nth 1 analysis)) (setq ctxt-indent (nth 2 analysis)) (setq prev-indent (nth 3 analysis)) From 9df2ba4b72df4517173177b94b17b30fba1e1879 Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Mon, 3 Apr 2023 01:54:20 -0700 Subject: [PATCH 4/7] disable aggressive paren rule temporarily --- scala-mode-indent.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index 553bb80..2dbff7d 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -434,7 +434,7 @@ Returns point or (point-min) if not inside a block." ;; { ( (`(?\{) 'left-boundary) ;; too aggressive? (`(?\{ ,_ . ,_) 'left-boundary) - (`(?\( ,_ . ,_) 'left-boundary) + ; (`(?\( ,_ . ,_) 'left-boundary) ;; (`(?\n ?.) 'dot-chain) (`(?\n ?. . ,_) 'dot-chain) From be4ef5c8c581803d11ae576b016a2fa30467d297 Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Sun, 4 Jun 2023 19:48:48 -0700 Subject: [PATCH 5/7] preliminary indentation support for `extension` --- scala-mode-indent.el | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index 2dbff7d..d1d2461 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -250,7 +250,9 @@ and the empty line") (regexp-opt '("abstract" "catch" "case" "class" "def" "do" "else" "final" "finally" "for" "if" "implicit" "import" "lazy" "new" "object" "override" "package" "private" "protected" "return" "sealed" - "throw" "trait" "try" "type" "val" "var" "while" "yield" "inline") + "throw" "trait" "try" "type" "val" "var" "while" "yield" "inline" + "extension" + ) 'words) "Words that we don't want to continue the previous line") @@ -438,6 +440,13 @@ Returns point or (point-min) if not inside a block." ;; (`(?\n ?.) 'dot-chain) (`(?\n ?. . ,_) 'dot-chain) + ;; extension + ;; + ;; FIXME: This is a hack that just checks if the previous line contains + ;; extension. The check for extension should check whether this is a + ;; single-def extension and for balanced parentheses, etc. to determine + ;; whether we emit a block token. + ((and `(extension . ,tail) (guard (memq ?\n tail))) 'block) ;; = (`(= ?\n . ,_) 'decl-lhs) ((and `(= ,_ . ,tail) (guard (memq ?\n tail))) 'after-decl) From 417dd61bbadc30d08e373afe1ab5b48d7103e10c Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Sun, 4 Jun 2023 19:49:04 -0700 Subject: [PATCH 6/7] add support for `do` as an align keyword like `then` and `else`. In Scala 3, `do-while` is dropped, and `do` is used only for separating the body of a `while` or `for` from the guard/comprehension. So, `do` would need to be indented like `then` or `else`. See: https://docs.scala-lang.org/scala3/reference/dropped-features/do-while.html# --- scala-mode-indent.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index d1d2461..32c34b8 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -372,7 +372,7 @@ is not on a run-on line." "\\|:\\(" scala-syntax:after-reserved-symbol-re "\\)")) (defconst scala-indent:forms-align-re - (regexp-opt '("yield" "then" "else" "catch" "finally") 'words)) + (regexp-opt '("do" "yield" "then" "else" "catch" "finally") 'words)) (defun scala-indent:forms-align-p (&optional point) "Returns `scala-syntax:beginning-of-code-line' for the line on @@ -520,6 +520,7 @@ Returns point or (point-min) if not inside a block." (`(with) 'block) ;; yield (`(yield . ,_) 'yield-from-comp) + (`(do . ,_) 'yield-from-comp) )) (defun scala-indent:relative-indent-by-elem (syntax-elem) From 5eef13b295b9d7a9903fa2eb6b73812e0899db2d Mon Sep 17 00:00:00 2001 From: Mehmet Emre Date: Sun, 4 Jun 2023 19:51:00 -0700 Subject: [PATCH 7/7] Preserve line numbers for blank lines. This allows differentiating between indenting a blank line and re-indenting the line before it. This situation occurs fairly often: it happens every time the user hits re turn to create a new line, which calls indentation function on the previous line and the newly created line separately. Before this fix, these two calls would incorrectly calculate the same indentation level, e.g. when the previous line just created a block. --- scala-mode-indent.el | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scala-mode-indent.el b/scala-mode-indent.el index 32c34b8..2d382c2 100644 --- a/scala-mode-indent.el +++ b/scala-mode-indent.el @@ -746,10 +746,17 @@ tokenization. The parser is not anything like well-formalized, but it can start at an arbitrary point in the buffer, and except in pathological cases, look at relatively few lines in order to make a good guess; and it is tolerant to a certain amount of incorrect or in-progress syntactic forms." - (let* ((initResult (scala-indent:find-analysis-start point)) + (let* ((line-no + ;; Get the line number while taking blanks into account. This allows + ;; differentiating between indenting at a blank line and re-indenting + ;; at the line right before it. + (line-number-at-pos + (save-excursion + (when point (goto-char point)) + (point)))) + (initResult (scala-indent:find-analysis-start point)) (point (car initResult)) (stack (cadr initResult)) - (line-no (line-number-at-pos point)) (analysis (scala-indent:analyze-context point stack)) (syntax-elem (list (nth 0 analysis))) (ctxt-line (nth 1 analysis))