emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/swift-mode 2cd111f 351/496: Fix indentation of multiline s


From: ELPA Syncer
Subject: [nongnu] elpa/swift-mode 2cd111f 351/496: Fix indentation of multiline strings
Date: Sun, 29 Aug 2021 11:34:05 -0400 (EDT)

branch: elpa/swift-mode
commit 2cd111f6b8b9061b8e3bff5e03e1d6135707b85d
Author: taku0 <mxxouy6x3m_github@tatapa.org>
Commit: taku0 <mxxouy6x3m_github@tatapa.org>

    Fix indentation of multiline strings
---
 swift-mode-indent.el           | 38 +++++++++++++++++++--
 swift-mode-lexer.el            | 75 ++++++++++++++++++++++++++++++++++++++++++
 swift-mode.el                  |  3 ++
 test/swift-files/strings.swift | 36 ++++++++++++++++++++
 4 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/swift-mode-indent.el b/swift-mode-indent.el
index 843b3a1..25963ce 100644
--- a/swift-mode-indent.el
+++ b/swift-mode-indent.el
@@ -151,14 +151,20 @@ declaration and its offset is `swift-mode:basic-offset'."
   "Return the indentation of the current line."
   (back-to-indentation)
 
-  (if (nth 4 (syntax-ppss))
+  (let ((parser-state (syntax-ppss)))
+    (cond
+     ((nth 4 parser-state)
       ;; If the 4th element of `(syntax-ppss)' is non-nil, the cursor is on
       ;; the 2nd or following lines of a multiline comment, because:
       ;;
       ;; - The 4th element of `(syntax-ppss)' is nil on the comment starter.
       ;; - We have called `back-to-indentation`.
-      (swift-mode:calculate-indent-of-multiline-comment)
-    (swift-mode:calculate-indent-of-code)))
+      (swift-mode:calculate-indent-of-multiline-comment))
+
+     ((eq (nth 3 parser-state) t)
+      (swift-mode:calculate-indent-of-multiline-string))
+     (t
+      (swift-mode:calculate-indent-of-code)))))
 
 (defun swift-mode:calculate-indent-of-multiline-comment ()
   "Return the indentation of the current line inside a multiline comment."
@@ -180,6 +186,32 @@ declaration and its offset is `swift-mode:basic-offset'."
           (swift-mode:calculate-indent-of-multiline-comment)
         (swift-mode:indentation (point) 0)))))
 
+(defun swift-mode:calculate-indent-of-multiline-string ()
+  "Return the indentation of the current line inside a multiline string."
+  (back-to-indentation)
+  (let ((string-beginning-position (nth 8 (syntax-ppss))))
+    (if (looking-at "\"\"\"")
+        ;; The last line.
+        (progn
+          (goto-char string-beginning-position)
+          (swift-mode:calculate-indent-of-expression
+           swift-mode:multiline-statement-offset))
+      (forward-line -1)
+      (back-to-indentation)
+      (if (<= (point) string-beginning-position)
+          ;; The cursor was on the 2nd line of the comment, so aligns with
+          ;; that line with offset.
+          (progn
+            (goto-char string-beginning-position)
+            (swift-mode:calculate-indent-of-expression
+             swift-mode:multiline-statement-offset))
+        ;; The cursor was on the 3rd or following lines of the comment, so
+        ;; aligns with a non-empty preceding line.
+        (if (eolp)
+            ;; The cursor is on an empty line, so seeks a non-empty-line.
+            (swift-mode:calculate-indent-of-multiline-string)
+          (swift-mode:indentation (point) 0))))))
+
 (defun swift-mode:calculate-indent-of-code ()
   "Return the indentation of the current line outside multiline comments."
   (back-to-indentation)
diff --git a/swift-mode-lexer.el b/swift-mode-lexer.el
index 21bdf78..6739b0f 100644
--- a/swift-mode-lexer.el
+++ b/swift-mode-lexer.el
@@ -152,6 +152,81 @@ END is the point after the token."
 
     table))
 
+(defun swift-mode:syntax-propertize (start end)
+  "Update text properties for multiline strings.
+Mark the beginning of and the end of multiline strings as general string
+delimiters between position START and END.
+Intended for `syntax-propertize-function'"
+  (remove-text-properties start end '(syntax-table nil))
+  (let* ((parser-state (syntax-ppss start))
+         (inside-string (nth 3 parser-state))
+         (comment-nesting (nth 4 parser-state))
+         (comment-beginning-position (nth 8 parser-state)))
+    (cond
+     ((eq inside-string t)
+      (swift-mode:syntax-propertize:end-of-multiline-string end))
+
+     (inside-string
+      (swift-mode:syntax-propertize:end-of-single-line-string end))
+
+     (comment-nesting
+      (goto-char comment-beginning-position)
+      (forward-comment (point-max)))))
+
+  (while (search-forward-regexp
+          (mapconcat #'regexp-quote '("\"\"\"" "\"" "//" "/*") "\\|")
+          end t)
+    (cond
+     ((equal "\"\"\"" (match-string-no-properties 0))
+      (put-text-property (match-beginning 0) (1+ (match-beginning 0))
+                         'syntax-table
+                         (string-to-syntax "|"))
+      (swift-mode:syntax-propertize:end-of-multiline-string end))
+
+     ((equal "\"" (match-string-no-properties 0))
+      (swift-mode:syntax-propertize:end-of-single-line-string end))
+
+     ((equal "//" (match-string-no-properties 0))
+      (goto-char (match-beginning 0))
+      (forward-comment (point-max)))
+
+     ((equal "/*" (match-string-no-properties 0))
+      (goto-char (match-beginning 0))
+      (forward-comment (point-max))))))
+
+(defun swift-mode:syntax-propertize:end-of-multiline-string (end)
+  "Move point to the end of multiline string.
+Assuming the cursor is on a multiline string.
+If the end of the string found, put a text property on it.
+If the multiline string go beyond END, stop there."
+  ;; FIXME string interpolation
+  (if (search-forward "\"\"\"" end t)
+      (if (swift-mode:escaped-p (match-beginning 0))
+          (swift-mode:syntax-propertize:end-of-multiline-string end)
+        (put-text-property (1- (point)) (point)
+                           'syntax-table
+                           (string-to-syntax "|")))
+    (goto-char end)))
+
+(defun swift-mode:syntax-propertize:end-of-single-line-string (end)
+  "Move point to the end of string.
+Assuming the cursor is on a string.
+If the multiline string go beyond END, stop there."
+  ;; FIXME string interpolation
+  (if (search-forward "\"" end t)
+      (when (swift-mode:escaped-p (match-beginning 0))
+        (swift-mode:syntax-propertize:end-of-single-line-string end))
+    (goto-char end)))
+
+(defun swift-mode:escaped-p (position)
+  "Return t if the POSITION is proceeded by odd number of backslashes.
+Return nil otherwise."
+  (let ((p position)
+        (count 0))
+    (while (eq (char-before p) ?\\)
+      (setq count (1+ count))
+      (setq p (1- p)))
+    (= (mod count 2) 1)))
 
 ;;; Lexers
 
diff --git a/swift-mode.el b/swift-mode.el
index afce622..5c80d1e 100644
--- a/swift-mode.el
+++ b/swift-mode.el
@@ -145,6 +145,9 @@ See `forward-sexp for ARG."
   (setq-local adaptive-fill-regexp comment-start-skip)
   (setq-local comment-multi-line t)
 
+  (setq-local parse-sexp-lookup-properties t)
+  (setq-local syntax-propertize-function #'swift-mode:syntax-propertize)
+
   (setq-local indent-tabs-mode nil)
   (setq-local indent-line-function #'swift-mode:indent-line)
 
diff --git a/test/swift-files/strings.swift b/test/swift-files/strings.swift
new file mode 100644
index 0000000..a961be5
--- /dev/null
+++ b/test/swift-files/strings.swift
@@ -0,0 +1,36 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+func f() {
+    let x = """
+      aaa
+      "
+      aaa
+      ""
+      aaa
+      \"""
+      aaa
+      ""
+      aaa
+      "
+      aaa
+      """ +
+      "abc"
+
+    let x = """
+      aaa
+      "
+        aaa // swift-mode:test:keep-indent
+        ""
+        aaa
+        \"""
+        aaa
+        ""
+        aaa
+        "
+        aaa
+      """ +
+      "abc"
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]