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

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

[nongnu] elpa/swift-mode 5448098 366/496: Improve functions related to d


From: ELPA Syncer
Subject: [nongnu] elpa/swift-mode 5448098 366/496: Improve functions related to defuns
Date: Sun, 29 Aug 2021 11:34:08 -0400 (EDT)

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

    Improve functions related to defuns
    
    More robust and sensible behaviors.
    Delcarations other than functions are now defun.
---
 swift-mode-beginning-of-defun.el | 469 +++++++++++++++++++++++++++------------
 1 file changed, 326 insertions(+), 143 deletions(-)

diff --git a/swift-mode-beginning-of-defun.el b/swift-mode-beginning-of-defun.el
index 9cd625c..dfac13e 100644
--- a/swift-mode-beginning-of-defun.el
+++ b/swift-mode-beginning-of-defun.el
@@ -1,6 +1,6 @@
 ;;; swift-mode-beginning-of-defun.el --- Major-mode for Apple's Swift 
programming language, beginning/end-of-defun. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2016 taku0
+;; Copyright (C) 2014-2017 taku0
 
 ;; Authors: taku0 (http://github.com/taku0)
 ;;
@@ -27,12 +27,10 @@
 
 ;; `beginning-of-defun' and `end-of-defun'
 ;;
-;; The end of a defun is just after the close curly brace.
+;; A defun is a declaration except local variable, "get", "set", "willSet",
+;; "didSet", or "case" within enum.
 ;;
-;; The beginning of a defun is the beginning of:
-;; - "func" keyword,
-;; - its modifiers or attributes,
-;; - comments on the same line.
+;; A defun include modifiers, attributes, and comments on the same line.
 ;;
 ;; `swift-mode:beginning-of-defun' moves the point to the beginning of a defun
 ;; that precedes (if the arg is positive) or follows (if the arg is negative)
@@ -87,46 +85,21 @@ and the region is not active."
         (pos (point)))
     (if (< 0 arg)
         ;; Moving backward
-        (progn
-          ;; `swift-mode:beginning-of-defun-1' assumes the point is after
-          ;; the open curly brace of defun. So moving the point to just after
-          ;; the open curly brace if the current statement has one.
-          (while (not
-                  (memq
-                   (swift-mode:token:type (swift-mode:forward-token))
-                   '({ implicit-\; \; } outside-of-buffer))))
-          (backward-char)
-          ;; Skips implicit-;
-          (forward-comment (point-max))
-          (when (eq (char-after) ?{)
-            (forward-char))
-
-          (setq result (swift-mode:beginning-of-defun-1
-                        #'swift-mode:backward-token-or-list))
-          (when (and result (< (point) pos))
-            (setq arg (1- arg)))
-
-          (while (and result (< 0 arg))
-            (setq result (swift-mode:beginning-of-defun-1
-                          #'swift-mode:backward-token-or-list))
-            (setq arg (1- arg))))
+        (while (and result (< 0 arg))
+          (let ((last-position (point)))
+            (setq result (swift-mode:beginning-of-defun-backward))
+            (when (< (point) last-position)
+              (setq arg (1- arg)))
+            (when (< 0 arg)
+              (swift-mode:backward-token-or-list))))
       ;; Moving forward
-      (setq result (swift-mode:beginning-of-defun-1
-                    (lambda ()
-                      (prog1 (swift-mode:forward-token-or-list)
-                        (forward-comment (point-max))))))
+      (setq result (swift-mode:beginning-of-defun-forward))
       (when (and result (< pos (point)))
         (setq arg (1+ arg)))
       (while (and result (< arg 0))
-        ;; Skips the current statement
-        (while (not
-                (memq
-                 (swift-mode:token:type (swift-mode:forward-token-or-list))
-                 '({} implicit-\; \; } outside-of-buffer))))
-        (setq result (swift-mode:beginning-of-defun-1
-                      (lambda ()
-                        (prog1 (swift-mode:forward-token-or-list)
-                          (forward-comment (point-max))))))
+        (swift-mode:forward-statement)
+        (forward-comment (point-max))
+        (setq result (swift-mode:beginning-of-defun-forward))
         (setq arg (1+ arg))))
     (and result
          (eq this-command 'swift-mode:beginning-of-defun)
@@ -135,76 +108,229 @@ and the region is not active."
          (push-mark pos))
     result))
 
-(defun swift-mode:beginning-of-defun-1 (next-token-function)
-  "Goto the beginning of a defun.
-
-NEXT-TOKEN-FUNCTION skips the preceding/following token."
-  (catch 'swift-mode:found-defun
-    (while (not (eq (swift-mode:token:type (funcall next-token-function))
-                    'outside-of-buffer))
-      (when (save-excursion (swift-mode:is-point-before-body-of-defun))
+(defun swift-mode:beginning-of-defun-backward ()
+  "Goto the beginning of a defun at or before the cursor."
+  (let ((keyword-token nil))
+    (while (null keyword-token)
+      (swift-mode:beginning-of-statement)
+      (setq keyword-token (swift-mode:find-defun-keyword))
+      (unless keyword-token
+        (let ((previous-token (swift-mode:backward-token-or-list)))
+          (when (eq (swift-mode:token:type previous-token) 'outside-of-buffer)
+            (setq keyword-token previous-token)))))
+    (not (eq (swift-mode:token:type keyword-token) 'outside-of-buffer))))
+
+(defun swift-mode:beginning-of-defun-forward ()
+  "Goto the beginning of a defun at or after the cursor.
+
+If the cursor is not at the beginning of a statement, the cursor may go back to
+the beginning of the current statement."
+  (let ((keyword-token nil))
+    (while (null keyword-token)
+      (setq keyword-token (swift-mode:find-defun-keyword))
+      (if keyword-token
+          (progn
+            (goto-char (swift-mode:token:start keyword-token))
+            (swift-mode:beginning-of-statement))
+        (let ((last-token (swift-mode:forward-statement)))
+          (when (eq (swift-mode:token:type last-token) 'outside-of-buffer)
+            (setq keyword-token last-token))
+          (forward-comment (point-max)))))
+    (not (eq (swift-mode:token:type keyword-token) 'outside-of-buffer))))
+
+(defun swift-mode:find-defun-keyword ()
+  "Find a defun keyword token in the current statement.
+
+If a keyword found in the current statement, return the token.
+Otherwise, return nil.
+The cursor must be at the beginning of a statement."
+  (save-excursion
+    (let ((token (swift-mode:find-defun-keyword-simple)))
+      (cond
+       ((member (swift-mode:token:text token) '("var" "let"))
+        (when (swift-mode:class-like-member-p) token))
+       ((equal (swift-mode:token:text token) "case")
+        (swift-mode:backward-sexps-until '({))
         (swift-mode:beginning-of-statement)
-        (throw 'swift-mode:found-defun t)))
-    nil))
-
-(defun swift-mode:is-point-before-body-of-defun ()
-  "Return t it the point is just before the body of a defun.
-
+        (let ((parent-token (swift-mode:find-defun-keyword-simple)))
+          (when (equal (swift-mode:token:text parent-token) "enum")
+            token)))
+       (t token)))))
+
+(defun swift-mode:find-defun-keyword-simple ()
+  "Find a defun keyword token in the current statement.
+
+If a keyword found in the current statement, return the token.
+Return the token for local variable declarations as well.
+Otherwise, return nil.
+The cursor must be at the beginning of a statement."
+  (let ((token (swift-mode:forward-token-or-list))
+        (defun-keywords
+          '("import" "typealias" "associatedtype"
+            "enum" "struct" "class" "protocol" "extension"
+            "func" "init" "deinit" "subscript" "get" "set" "willSet" "didSet"
+            "prefix" "postfix" "infix" "precedencegroup"
+            "var" "let"
+            "case"))
+        (stop-tokens '(\; implicit-\; {} } \) \]
+                       anonymous-function-parameter-in outside-of-buffer)))
+    (while (not (or
+                 (memq (swift-mode:token:type token) stop-tokens)
+                 (member (swift-mode:token:text token) defun-keywords)))
+      (setq token (swift-mode:forward-token-or-list)))
+    (when (member (swift-mode:token:text token) defun-keywords)
+      token)))
+
+(defun swift-mode:class-like-member-p ()
+  "Return t if the cursor is on a member of a class-like declaration.
+Also return t if the cursor is on a global declaration.
 Return nil otherwise."
-  (and
-   (eq (char-after) ?{)
+  (or
+   (let ((parent (swift-mode:backward-sexps-until '({))))
+     (eq (swift-mode:token:type parent) 'outside-of-buffer))
    (progn
-     ;; Skips implicit ;
-     (forward-comment (- (point)))
-     (let* ((defun-keywords '("class" "struct" "protocol" "enum" "extension"
-                              "func" "operator" "var" "get" "set" "willSet"
-                              "didSet" "deinit" "subscript"))
-            (previous-token (swift-mode:backward-token-or-list))
-            (previous-type (swift-mode:token:type previous-token))
-            (previous-text (swift-mode:token:text previous-token)))
-       (while (and
-               (not (eq previous-type 'outside-of-buffer))
-               (not (memq previous-type swift-mode:statement-parent-tokens))
-               (not (member previous-text swift-mode:statement-parent-tokens))
-               (not (member previous-text defun-keywords))
-               (not (and (equal previous-text "init")
-                         (save-excursion
-                           ;; Excludes self.init() {}
-                           (not
-                            (equal
-                             (swift-mode:token:text 
(swift-mode:backward-token))
-                             "."))))))
-         (setq previous-token (swift-mode:backward-token-or-list))
-         (setq previous-type (swift-mode:token:type previous-token))
-         (setq previous-text (swift-mode:token:text previous-token)))
-       (or (equal previous-text "init")
-           (member previous-text defun-keywords))))))
+     (swift-mode:beginning-of-statement)
+     (member
+      (swift-mode:token:text (swift-mode:find-defun-keyword-simple))
+      '("enum" "struct" "class" "protocol" "extension")))))
 
 (defun swift-mode:beginning-of-statement ()
-  "Move backward to the beginning of a statement or some kind of expression.
+  "Move backward to the beginning of a statement.
+Statements include comments on the same line.
 
 Intended for internal use."
-  (let ((parent (swift-mode:backward-sexps-until
-                 swift-mode:statement-parent-tokens)))
-    (if (and
-         (eq (swift-mode:token:type parent) 'implicit-\;)
-         (save-excursion
-           (goto-char (swift-mode:token:end parent))
-           (eq
-            (swift-mode:token:type (swift-mode:forward-token))
-            '{)))
-        (progn
-          (forward-comment (- (point)))
-          (swift-mode:beginning-of-statement))
-      ;; Excludes comments on previous lines.
-      (goto-char (swift-mode:token:end parent))
+  (let ((pos (point))
+        (previous-token (save-excursion
+                          (forward-comment (- (point)))
+                          (swift-mode:backward-token))))
+    (forward-comment (point-max))
+    (swift-mode:goto-non-comment-bol)
+    (swift-mode:skip-whitespaces)
+
+    ;; We have three cases:
+    ;;
+    ;; func foo() {
+    ;; }
+    ;;
+    ;; // A
+    ;;
+    ;; /* B */ func /* C */ bar() {
+    ;; }
+    (cond
+     ((or (< pos (point))
+          (memq (swift-mode:token:type
+                 (save-excursion (swift-mode:forward-token)))
+                '(} \) \])))
+      ;; The pos is at A or just before closing parens.
+      (if (memq (swift-mode:token:type previous-token)
+                swift-mode:statement-parent-tokens)
+          ;; At beginning of a block. Goes up.
+          (goto-char (swift-mode:token:start previous-token))
+        ;; Otherwise, skips implicit semicolons.
+        (goto-char (swift-mode:token:end previous-token)))
       (forward-comment (- (point)))
-      (setq parent (save-excursion (swift-mode:backward-token)))
+      (swift-mode:do-beginning-of-statement)
+      (when (< pos (point))
+        ;; no statements found
+        (goto-char (point-min))))
+     ((< (point) (swift-mode:token:end previous-token))
+      ;; The pos is at C.
+      (goto-char (swift-mode:token:end previous-token))
+      (swift-mode:do-beginning-of-statement))
+     (t
+      ;; The pos is at B.
       (forward-comment (point-max))
-      (swift-mode:goto-non-comment-bol)
-      (when (< (point) (swift-mode:token:end parent))
-        (goto-char (swift-mode:token:end parent)))
-      (swift-mode:skip-whitespaces))))
+      (swift-mode:do-beginning-of-statement)))))
+
+(defun swift-mode:do-beginning-of-statement ()
+  "Move backward to the beginning of a statement.
+Statements include comments on the same line.
+
+Intended for internal use."
+  (let (parent)
+    (while (progn
+             (setq parent (swift-mode:backward-sexps-until
+                           swift-mode:statement-parent-tokens))
+             (swift-mode:pseudo-implicit-semicolon-p parent)))
+    (goto-char (swift-mode:token:end parent))
+    ;; Excludes comments on previous lines but includes comments on the same
+    ;; line.
+    (forward-comment (- (point)))
+    (setq parent (save-excursion (swift-mode:backward-token)))
+    (forward-comment (point-max))
+    (swift-mode:goto-non-comment-bol)
+    (when (< (point) (swift-mode:token:end parent))
+      (goto-char (swift-mode:token:end parent)))
+    (swift-mode:skip-whitespaces)))
+
+(defun swift-mode:end-of-statement ()
+  "Move forward to the end of a statement.
+
+When called at the end of a statement, keep the position.
+
+Return the next token.
+Intended for internal use."
+  (let ((pos (point))
+        (previous-token (save-excursion (swift-mode:backward-token)))
+        next-token)
+    (cond
+     ((and
+       (memq (swift-mode:token:type previous-token)
+             '(\; anonymous-function-parameter-in))
+       (eq (swift-mode:token:end previous-token) pos))
+      ;; Already at the eod of statement.  Returns next token.
+      (save-excursion (swift-mode:forward-token)))
+     ((memq (swift-mode:token:type previous-token)
+            '(implicit-\; outside-of-buffer))
+      ;; Between statements, or before the first statement.
+      (swift-mode:forward-statement))
+     ((progn
+        (setq next-token (save-excursion (swift-mode:forward-token)))
+        (and (memq (swift-mode:token:type next-token)
+                   '(implicit-\; } outside-of-buffer))
+             (eq (swift-mode:token:end previous-token) pos)))
+      ;; Already at the end of statement.  Returns next token.
+      next-token)
+     (t
+      (swift-mode:forward-statement)))))
+
+(defun swift-mode:forward-statement ()
+  "Move forward to the end of a statement.
+
+Return the next token.
+Intended for internal use."
+  (forward-comment (point-max))
+  (let ((pos (point))
+        token)
+    (while (progn
+             (setq token (swift-mode:forward-token-or-list))
+             (or
+              (not (memq (swift-mode:token:type token)
+                         '(\; implicit-\; } anonymous-function-parameter-in
+                           outside-of-buffer)))
+              (swift-mode:pseudo-implicit-semicolon-p token))))
+    (while (eq (swift-mode:token:type
+                (save-excursion (swift-mode:forward-token)))
+               '\;)
+      (setq token (swift-mode:forward-token)))
+    (if (memq (swift-mode:token:type token)
+              '(\; anonymous-function-parameter-in))
+        (goto-char (swift-mode:token:end token))
+      (goto-char (swift-mode:token:start token)))
+    (cond
+     ((eq (swift-mode:token:type token) 'outside-of-buffer)
+      (forward-comment (- (point)))
+      (when (< (point) pos)
+        (goto-char (swift-mode:token:end token)))
+      token)
+     ((eq (swift-mode:token:type token) '})
+      (forward-comment (- (point)))
+      (if (< (point) pos)
+          (progn
+            (goto-char (swift-mode:token:end token))
+            (swift-mode:end-of-statement))
+        token))
+     (t token))))
 
 (defun swift-mode:end-of-defun (&optional arg)
   "Move forward to the end of a defun.
@@ -217,19 +343,29 @@ Push mark at previous position if this is called as a 
command, not repeatedly,
 and the region is not active."
   (interactive "p")
   (setq arg (or arg 1))
-  (let (result
+  (let ((result t)
         (pos (point)))
     (if (<= 0 arg)
-        (while (< 0 arg)
-          (setq result (swift-mode:end-of-defun-1
-                        #'swift-mode:forward-token-or-list))
-          (setq arg (1- arg)))
-      (while (< arg 0)
-        (setq result (swift-mode:end-of-defun-1
-                      (lambda ()
-                        (prog1 (swift-mode:backward-token-or-list)
-                          (forward-comment (- (point)))))))
-        (setq arg (1+ arg))))
+        ;; Moving forward
+        (while (and result (< 0 arg))
+          (swift-mode:forward-statement)
+          (when (save-excursion
+                  (swift-mode:beginning-of-statement)
+                  (swift-mode:find-defun-keyword))
+            (setq arg (1- arg)))
+          (when (and (< 0 arg)
+                      (eq (swift-mode:token:type (swift-mode:forward-token))
+                          'outside-of-buffer))
+            (setq result nil)))
+      ;; Moving backward
+      (while (and result (< arg 0))
+        (setq result (swift-mode:end-of-statement-backward))
+        (let ((statement-end-position (point)))
+          (swift-mode:beginning-of-statement)
+          (when (swift-mode:find-defun-keyword)
+            (setq arg (1+ arg)))
+          (when (eq arg 0)
+            (goto-char statement-end-position)))))
     (and result
          (eq this-command 'swift-mode:end-of-defun)
          (not (eq last-command 'swift-mode:end-of-defun))
@@ -237,19 +373,69 @@ and the region is not active."
          (push-mark pos))
     result))
 
-(defun swift-mode:end-of-defun-1 (next-token-function)
-  "Goto the end of a defun.
+(defun swift-mode:end-of-statement-backward ()
+  "Move backward to the end of a statement.
+
+Return t if a statement found.  Return nil otherwise.
+When called at the end of a statement, find the previous one.
+Intended for internal use."
+  (when (save-excursion
+          (let ((pos (point))
+                (token (swift-mode:backward-token)))
+            (and
+             (memq (swift-mode:token:type token)
+                   '(\; anonymous-function-parameter-in))
+             (eq (swift-mode:token:end token) pos))))
+    (swift-mode:backward-token))
+  (or
+   ;; last statement in non-empty block
+   (and
+    (let ((next-token (save-excursion (swift-mode:forward-token))))
+      (memq (swift-mode:token:type next-token) '(} outside-of-buffer)))
+    (let ((previous-token (save-excursion
+                            (forward-comment (- (point)))
+                            (swift-mode:backward-token))))
+      (not (eq (swift-mode:token:type previous-token) '{)))
+    (let ((pos (point)))
+      (forward-comment (- (point)))
+      (< (point) pos)))
+   ;; other cases
+   (let (token)
+     (while (progn
+              (setq token (swift-mode:backward-sexps-until
+                           '(\; implicit-\; anonymous-function-parameter-in)))
+              (swift-mode:pseudo-implicit-semicolon-p token)))
+     (when (memq (swift-mode:token:type token)
+                 '(\; anonymous-function-parameter-in))
+       (goto-char (swift-mode:token:end token)))
+     (not (eq (swift-mode:token:type token) 'outside-of-buffer)))))
+
+(defun swift-mode:pseudo-implicit-semicolon-p (token)
+  "Return t if TOKEN is an implicit semicolon not at end of a statement.
+
+Return nil otherwise."
+  ;; func foo() // implicit semicolon here
+  ;; {
+  ;; }
+  ;;
+  ;; if foo {
+  ;; } // implicit semicolon here
+  ;; else {
+  ;; }
+  ;;
+  ;; do {
+  ;; } // implicit semicolon here
+  ;; catch {
+  ;; }
+  (and
+   (eq (swift-mode:token:type token) 'implicit-\;)
+   (save-excursion
+     (goto-char (swift-mode:token:end token))
+     (let ((next-token (swift-mode:forward-token)))
+       (or
+        (eq (swift-mode:token:type next-token) '{)
+        (member (swift-mode:token:text next-token) '("catch" "else")))))))
 
-NEXT-TOKEN-FUNCTION skips the preceding/following token."
-  (catch 'swift-mode:found-defun
-    (while (not (eq (swift-mode:token:type (funcall next-token-function))
-                    'outside-of-buffer))
-      (when (and (eq (char-before) ?})
-                 (save-excursion
-                   (backward-list)
-                   (swift-mode:is-point-before-body-of-defun)))
-        (throw 'swift-mode:found-defun t)))
-    nil))
 
 (defun swift-mode:mark-defun (&optional allow-extend)
   "Put mark at the end of defun, point at the beginning of defun.
@@ -275,18 +461,19 @@ nesting level, mark the whole outer defun."
                (swift-mode:end-of-defun)
              (swift-mode:beginning-of-defun))
            (point)))
-        ;; Marks the whole outer defun if it has lesser nesting level.
-        (if forward-p
-            (goto-char (min (point)
-                            (save-excursion
-                              (goto-char (mark))
-                              (swift-mode:beginning-of-defun)
-                              (point))))
-          (goto-char (max (point)
-                          (save-excursion
-                            (goto-char (mark))
-                            (swift-mode:end-of-defun)
-                            (point))))))
+        ;; Marks the whole outer defun if the mark got out of the outer defun.
+        (goto-char
+         (if forward-p
+             (min (point)
+                  (save-excursion
+                    (goto-char (mark))
+                    (swift-mode:beginning-of-defun)
+                    (point)))
+           (max (point)
+                (save-excursion
+                  (goto-char (mark))
+                  (swift-mode:end-of-defun)
+                  (point))))))
     ;; Marks new region.
     (let ((region
            (cond
@@ -361,7 +548,7 @@ nesting level, mark the whole outer defun."
 (defun swift-mode:narrow-to-defun (&optional include-comments)
   "Make text outside current defun invisible.
 
-If the point is between defuns, mark depend on
+If the point is between defuns, narrow depend on
 `swift-mode:mark-defun-preference'.
 
 Preceding comments are included if INCLUDE-COMMENTS is non-nil.
@@ -372,7 +559,6 @@ Interactively, the behavior depends on 
‘narrow-to-defun-include-comments’."
         extended)
     (save-excursion
       (widen)
-
       (setq region
             (cond
              ((eq swift-mode:mark-defun-preference 'containing)
@@ -381,10 +567,8 @@ Interactively, the behavior depends on 
‘narrow-to-defun-include-comments’."
               (swift-mode:preceding-defun-region))
              ((eq swift-mode:mark-defun-preference 'following)
               (swift-mode:following-defun-region))))
-
       (setq extended
             (and region (swift-mode:extend-defun-region-with-spaces region)))
-
       (when (and extended include-comments)
         (save-excursion
           (goto-char (car extended))
@@ -395,7 +579,6 @@ Interactively, the behavior depends on 
‘narrow-to-defun-include-comments’."
           ;; Includes indentation.
           (skip-syntax-backward " ")
           (setcar extended (point))))
-
       (if extended
           (narrow-to-region (car extended) (cdr extended))
         (when (called-interactively-p 'interactive)



reply via email to

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