|
34 | 34 |
|
35 | 35 | (require 'swift-mode-lexer) |
36 | 36 |
|
| 37 | +;;; Customizations |
| 38 | + |
37 | 39 | ;;;###autoload |
38 | 40 | (defcustom swift-mode:basic-offset 4 |
39 | 41 | "Amount of indentation for block contents." |
|
83 | 85 | :group 'swift |
84 | 86 | :safe 'booleanp) |
85 | 87 |
|
| 88 | +;;;###autoload |
| 89 | +(defcustom swift-mode:highlight-anchor nil |
| 90 | + "Highlight anchor point for indentation if non-nil. |
| 91 | +
|
| 92 | +Intended for debugging." |
| 93 | + :type 'boolean |
| 94 | + :group 'swift |
| 95 | + :safe 'booleanp) |
| 96 | + |
| 97 | +;;; Constants and variables |
| 98 | + |
86 | 99 | (defconst swift-mode:statement-parent-tokens |
87 | 100 | '(implicit-\; \; case-: { \( \[ anonymous-function-parameter-in) |
88 | 101 | "Parent tokens for statements.") |
|
92 | 105 | '(\, < supertype-: "where" "if" "guard" "while" "for" "catch")) |
93 | 106 | "Parent tokens for expressions.") |
94 | 107 |
|
| 108 | +(defvar-local swift-mode:anchor-overlay nil) |
| 109 | +(defvar-local swift-mode:anchor-overlay-timer nil) |
| 110 | + |
| 111 | +;;; Indentation struct |
| 112 | + |
| 113 | +(defun swift-mode:indentation (point offset) |
| 114 | + "Construct and return a indentation. |
| 115 | +
|
| 116 | +POINT is the position of the anchor point, such as the start of the previous |
| 117 | +line or the start of the class declaration. |
| 118 | +OFFSET is the offset from the anchor point. For example, when indenting the |
| 119 | +first line of a class body, its anchor point is the start of the class |
| 120 | +declaration and its offset is `swift-mode:basic-offset'." |
| 121 | + (list point offset)) |
| 122 | + |
| 123 | +(defun swift-mode:indentation:point (indentation) |
| 124 | + "Return the point of INDENTATION." |
| 125 | + (nth 0 indentation)) |
| 126 | + |
| 127 | +(defun swift-mode:indentation:offset (indentation) |
| 128 | + "Return the offset of INDENTATION." |
| 129 | + (nth 1 indentation)) |
| 130 | + |
| 131 | +;;; Indentation logics |
| 132 | + |
95 | 133 | (defun swift-mode:indent-line () |
96 | 134 | "Indent the current line." |
97 | | - (let ((indent (save-excursion (swift-mode:calculate-indent))) |
98 | | - (current-indent |
99 | | - (save-excursion (back-to-indentation) (current-column)))) |
| 135 | + (let* ((indentation (save-excursion (swift-mode:calculate-indent))) |
| 136 | + (indentation-column |
| 137 | + (save-excursion |
| 138 | + (goto-char (swift-mode:indentation:point indentation)) |
| 139 | + (+ (current-column) (swift-mode:indentation:offset indentation)))) |
| 140 | + (current-indent |
| 141 | + (save-excursion (back-to-indentation) (current-column)))) |
100 | 142 | (if (<= (current-column) current-indent) |
101 | 143 | ;; The cursor is on the left margin. Moving to the new indent. |
102 | | - (indent-line-to indent) |
| 144 | + (indent-line-to indentation-column) |
103 | 145 | ;; Keeps current relative position. |
104 | | - (save-excursion (indent-line-to indent))))) |
| 146 | + (save-excursion (indent-line-to indentation-column))) |
| 147 | + (when swift-mode:highlight-anchor |
| 148 | + (swift-mode:highlight-anchor indentation)))) |
105 | 149 |
|
106 | 150 | (defun swift-mode:calculate-indent () |
107 | 151 | "Return the indentation of the current line." |
|
128 | 172 | (progn |
129 | 173 | (goto-char comment-beginning-position) |
130 | 174 | (forward-char) |
131 | | - (current-column)) |
| 175 | + (swift-mode:indentation (point) 0)) |
132 | 176 | ;; The cursor was on the 3rd or following lines of the comment, so aligns |
133 | 177 | ;; with a non-empty preceding line. |
134 | 178 | (if (eolp) |
135 | 179 | ;; The cursor is on an empty line, so seeks a non-empty-line. |
136 | 180 | (swift-mode:calculate-indent-of-multiline-comment) |
137 | | - (current-column))))) |
| 181 | + (swift-mode:indentation (point) 0))))) |
138 | 182 |
|
139 | 183 | (defun swift-mode:calculate-indent-of-code () |
140 | 184 | "Return the indentation of the current line outside multiline comments." |
|
150 | 194 | (cond |
151 | 195 | ;; Beginning of the buffer |
152 | 196 | ((eq previous-type 'outside-of-buffer) |
153 | | - 0) |
| 197 | + (swift-mode:indentation (point-min) 0)) |
154 | 198 |
|
155 | 199 | ;; Before } on the same line |
156 | 200 | ((and next-is-on-same-line (eq next-type '})) |
@@ -837,7 +881,7 @@ This is also known as Utrecht-style in the Haskell community." |
837 | 881 | ;; Aligns with the end of the parent. |
838 | 882 | (goto-char (swift-mode:token:end parent)) |
839 | 883 | (backward-char) |
840 | | - (current-column)))) |
| 884 | + (swift-mode:indentation (point) 0)))) |
841 | 885 |
|
842 | 886 | (defun swift-mode:calculate-indent-after-comma () |
843 | 887 | "Return indentation after comma. |
@@ -1139,13 +1183,13 @@ is the symbol `any', it matches all tokens." |
1139 | 1183 | (when (< (point) parent-end) |
1140 | 1184 | (goto-char parent-end)) |
1141 | 1185 | (swift-mode:skip-whitespaces) |
1142 | | - (+ (or offset 0) (current-column)))) |
| 1186 | + (swift-mode:indentation (point) (or offset 0)))) |
1143 | 1187 |
|
1144 | 1188 | (defun swift-mode:align-with-current-line (&optional offset) |
1145 | 1189 | "Return indentation of the current line with OFFSET." |
1146 | 1190 | (swift-mode:goto-non-comment-bol) |
1147 | 1191 | (swift-mode:skip-whitespaces) |
1148 | | - (+ (or offset 0) (current-column))) |
| 1192 | + (swift-mode:indentation (point) (or offset 0))) |
1149 | 1193 |
|
1150 | 1194 | (defun swift-mode:backward-token-or-list () |
1151 | 1195 | "Move point to the start position of the previous token or list. |
@@ -1464,6 +1508,26 @@ See `indent-new-comment-line' for SOFT." |
1464 | 1508 | (delete-horizontal-space) |
1465 | 1509 | (forward-char)))) |
1466 | 1510 |
|
| 1511 | +(defun swift-mode:highlight-anchor (indentation) |
| 1512 | + "Highlight the anchor point of the INDENTATION." |
| 1513 | + (move-overlay |
| 1514 | + swift-mode:anchor-overlay |
| 1515 | + (swift-mode:indentation:point indentation) |
| 1516 | + (1+ (swift-mode:indentation:point indentation))) |
| 1517 | + |
| 1518 | + (overlay-put swift-mode:anchor-overlay 'face 'highlight) |
| 1519 | + |
| 1520 | + (when swift-mode:anchor-overlay-timer |
| 1521 | + (cancel-timer swift-mode:anchor-overlay-timer)) |
| 1522 | + |
| 1523 | + (setq swift-mode:anchor-overlay-timer |
| 1524 | + (run-at-time |
| 1525 | + "1 sec" |
| 1526 | + nil |
| 1527 | + (lambda () |
| 1528 | + (delete-overlay swift-mode:anchor-overlay) |
| 1529 | + (setq swift-mode:anchor-overlay-timer nil))))) |
| 1530 | + |
1467 | 1531 | (provide 'swift-mode-indent) |
1468 | 1532 |
|
1469 | 1533 | ;;; swift-mode-indent.el ends here |
0 commit comments