8484 :group 'swift
8585 :safe 'booleanp )
8686
87+ (defcustom swift-mode:break-line-before-comment-close t
88+ " If non-nil, break line before the closing delimiter of multiline comments."
89+ :type 'boolean
90+ :group 'swift
91+ :safe 'booleanp )
92+
8793(defcustom swift-mode:highlight-anchor nil
8894 " Highlight anchor point for indentation if non-nil.
8995
@@ -172,22 +178,55 @@ declaration and its offset is `swift-mode:basic-offset'."
172178(defun swift-mode:calculate-indent-of-multiline-comment ()
173179 " Return the indentation of the current line inside a multiline comment."
174180 (back-to-indentation )
175- (let ((comment-beginning-position (nth 8 (syntax-ppss ))))
181+ (let ((comment-beginning-position (nth 8 (syntax-ppss )))
182+ (starts-with-asterisk (eq (char-after ) ?* )))
176183 (forward-line -1 )
177184 (back-to-indentation )
178- (if (<= (point ) comment-beginning-position)
179- ; ; The cursor was on the 2nd line of the comment, so aligns with
180- ; ; the asterisk of the comment starter.
181- (progn
182- (goto-char comment-beginning-position)
183- (forward-char )
184- (swift-mode:indentation (point ) 0 ))
185- ; ; The cursor was on the 3rd or following lines of the comment, so aligns
186- ; ; with a non-empty preceding line.
187- (if (eolp )
188- ; ; The cursor is on an empty line, so seeks a non-empty-line.
189- (swift-mode:calculate-indent-of-multiline-comment)
190- (swift-mode:indentation (point ) 0 )))))
185+ (cond
186+ ((<= (point ) comment-beginning-position)
187+ ; ; The cursor was on the 2nd line of the comment.
188+ (goto-char comment-beginning-position)
189+ (forward-char )
190+ ; ; If there are extra characters or spaces after asterisks, aligns with
191+ ; ; the first non-space character or end of line. Otherwise, aligns with
192+ ; ; the first asterisk.
193+ (when (and
194+ (looking-at " \\ **[^*\n ]+" )
195+ (not (and swift-mode:prepend-asterisk-to-comment-line
196+ starts-with-asterisk)))
197+ (skip-chars-forward " *" )
198+ (skip-syntax-forward " " ))
199+ (swift-mode:indentation (point ) 0 ))
200+
201+ ; ; The cursor was on the 3rd or following lines of the comment.
202+
203+ ((= (save-excursion
204+ (forward-line )
205+ (back-to-indentation )
206+ (point ))
207+ (save-excursion
208+ (goto-char comment-beginning-position)
209+ (if (forward-comment 1 )
210+ (progn
211+ (backward-char )
212+ (skip-chars-backward " *" )
213+ (point ))
214+ -1 )))
215+ ; ; Before the closing delimiter. Aligns with the first asterisk of the
216+ ; ; opening delimiter.
217+ (goto-char comment-beginning-position)
218+ (forward-char )
219+ (swift-mode:indentation (point ) 0 ))
220+
221+ ; ; Otherwise, aligns with a non-empty preceding line.
222+
223+ ((and (bolp ) (eolp ))
224+ ; ; The previous line is empty, so seeks a non-empty-line.
225+ (swift-mode:calculate-indent-of-multiline-comment))
226+
227+ (t
228+ ; ; The previous line is not empty, so aligns to this line.
229+ (swift-mode:indentation (point ) 0 )))))
191230
192231(defun swift-mode:calculate-indent-of-multiline-string ()
193232 " Return the indentation of the current line inside a multiline string."
@@ -213,7 +252,7 @@ declaration and its offset is `swift-mode:basic-offset'."
213252 swift-mode:multiline-statement-offset))
214253 ; ; The cursor was on the 3rd or following lines of the comment, so
215254 ; ; aligns with a non-empty preceding line.
216- (if (eolp )
255+ (if (and ( bolp ) ( eolp ) )
217256 ; ; The cursor is on an empty line, so seeks a non-empty-line.
218257 (swift-mode:calculate-indent-of-multiline-string)
219258 (swift-mode:indentation (point ) 0 ))))))
@@ -1527,15 +1566,14 @@ Return nil otherwise."
15271566 " Skips forward whitespaces and newlines."
15281567 (skip-syntax-forward " >" ))
15291568
1530- (defun swift-mode:incomplete-comment-p ()
1531- " Return t if the point is inside an incomplete comment.
1569+ (defun swift-mode:incomplete-comment-p (chunk )
1570+ " Return t if the CHUNK is incomplete comment.
15321571
15331572Return nil otherwise."
1534- (let ((chunk (swift-mode:chunk-after)))
1535- (and (swift-mode:chunk:comment-p chunk)
1536- (save-excursion
1537- (goto-char (swift-mode:chunk:start chunk))
1538- (not (forward-comment 1 ))))))
1573+ (and (swift-mode:chunk:comment-p chunk)
1574+ (save-excursion
1575+ (goto-char (swift-mode:chunk:start chunk))
1576+ (not (forward-comment 1 )))))
15391577
15401578(defun swift-mode:indent-new-comment-line (&optional soft )
15411579 " Break the line at the point and indent the new line.
@@ -1550,20 +1588,21 @@ See `indent-new-comment-line' for SOFT."
15501588 (if soft (insert-and-inherit ?\n ) (newline 1 ))
15511589 (delete-horizontal-space )
15521590
1591+ ; ; Inserts a prefix and indents the line.
15531592 (cond
15541593 ((not (swift-mode:chunk:comment-p chunk))
15551594 (indent-according-to-mode ))
15561595
15571596 ((swift-mode:chunk:single-line-comment-p chunk)
1558- (insert-before-markers- and-inherit
1597+ (insert-and-inherit
15591598 (save-excursion
15601599 (goto-char comment-beginning-position)
15611600 (looking-at " /+\\ s *" )
15621601 (match-string-no-properties 0 )))
15631602 (indent-according-to-mode ))
15641603
15651604 ((not comment-multi-line)
1566- (insert-before-markers- and-inherit
1605+ (insert-and-inherit
15671606 (save-excursion
15681607 (goto-char comment-beginning-position)
15691608 (looking-at " /\\ *+\\ s *" )
@@ -1573,33 +1612,98 @@ See `indent-new-comment-line' for SOFT."
15731612 (forward-line 0 )
15741613 (backward-char )
15751614 (delete-horizontal-space )
1576- (insert-before-markers- and-inherit " */" ))
1615+ (insert-and-inherit " */" ))
15771616 (indent-according-to-mode ))
15781617
1618+ (t
1619+ (swift-mode:format-multiline-comment-line-after-newline chunk soft)))
1620+
1621+ ; ; Cleans up the previous line.
1622+ (save-excursion
1623+ (forward-line 0 )
1624+ (backward-char )
1625+ (delete-horizontal-space ))))
1626+
1627+ (defun swift-mode:format-multiline-comment-line-after-newline (chunk soft )
1628+ " Insert prefix and indent current line in multiline comment.
1629+
1630+ The point is assumed inside multiline comment and just after newline.
1631+
1632+ The closing delimiter is also inserted and/or formatted depending on custom
1633+ variables `swift-mode:auto-close-multiline-comment' and
1634+ `swift-mode:break-line-before-comment-close' .
1635+
1636+ CHUNK is the comment chunk.
1637+
1638+ See `indent-new-comment-line' for SOFT."
1639+ (let ((comment-beginning-position (swift-mode:chunk:start chunk)))
1640+ (cond
15791641 ((save-excursion
15801642 (forward-line -1 )
15811643 (<= (point ) comment-beginning-position))
15821644 ; ; The cursor was on the 2nd line of the comment.
1583- ; ; Uses default prefix.
1584- (when swift-mode:prepend-asterisk-to-comment-line
1585- (insert-before-markers-and-inherit " *" )
1586- (when swift-mode:insert-space-after-asterisk-in-comment
1587- (insert-before-markers-and-inherit " " )))
1645+
1646+ ; ; If the comment have only one line, delete a space after asterisk.
1647+ ; ;
1648+ ; ; Example:
1649+ ; ; /** aaa */
1650+ ; ; ↓
1651+ ; ; /**
1652+ ; ; aaa
1653+ ; ; */
1654+ ; ;
1655+ ; ; /** aaa
1656+ ; ; */
1657+ ; ; ↓
1658+ ; ; /**
1659+ ; ; aaa
1660+ ; ; */
1661+ (when (= (line-beginning-position )
1662+ (save-excursion
1663+ (goto-char comment-beginning-position)
1664+ (forward-comment 1 )
1665+ (line-beginning-position )))
1666+ (save-excursion
1667+ (goto-char comment-beginning-position)
1668+ (forward-char )
1669+ (skip-chars-forward " *" )
1670+ (when (looking-at " [ \t ]*$" )
1671+ (delete-char 1 ))))
1672+
1673+ ; ; If the point is just before the closing delimiter, breaks the line.
1674+ (when (and swift-mode:break-line-before-comment-close
1675+ (= (point )
1676+ (save-excursion
1677+ (goto-char comment-beginning-position)
1678+ (if (forward-comment 1 )
1679+ (progn
1680+ (backward-char )
1681+ (skip-chars-backward " *" )
1682+ (point ))
1683+ -1 ))))
1684+ (save-excursion
1685+ (if soft (insert-and-inherit ?\n ) (newline 1 ))
1686+ (indent-according-to-mode )))
1687+
1688+ ; ; Invokes `swift-mode:indent-line`
15881689 (indent-according-to-mode )
1589- (insert-before-markers-and-inherit
1590- (save-excursion
1591- (goto-char comment-beginning-position)
1592- (forward-char 1 )
1593- (looking-at " \\ **\\ (\\ s *\\ )" )
1594- (let ((prefix (match-string-no-properties 0 )))
1595- (if (= (length (match-string-no-properties 1 )) 0 )
1596- " "
1597- (substring
1598- (replace-regexp-in-string " \\ *" " " prefix)
1599- (if swift-mode:prepend-asterisk-to-comment-line
1600- (if swift-mode:insert-space-after-asterisk-in-comment 2 1 )
1601- 0 )
1602- (length prefix)))))))
1690+
1691+ ; ; Inserts or replaces a space to an asterisk.
1692+ (when swift-mode:prepend-asterisk-to-comment-line
1693+ (let ((columns-from-end (- (line-end-position ) (point ))))
1694+ (move-to-column
1695+ (save-excursion
1696+ (goto-char comment-beginning-position)
1697+ (forward-char )
1698+ (current-column )))
1699+ (insert-and-inherit " *" )
1700+ (when (eq (char-after ) ?\s )
1701+ (delete-char 1 ))
1702+ (when (and
1703+ swift-mode:insert-space-after-asterisk-in-comment
1704+ (not (eq (char-after ) ?\s )))
1705+ (insert-and-inherit " " ))
1706+ (goto-char (- (line-end-position ) columns-from-end)))))
16031707
16041708 ; ; The cursor was on the 3nd or following lines of
16051709 ; ; the comment.
@@ -1611,39 +1715,34 @@ See `indent-new-comment-line' for SOFT."
16111715 (forward-line -1 )
16121716 (looking-at " \\ s *\\ (\\ *+\\ s *\\ )" )))
16131717 ; ; The previous line has a prefix. Uses it.
1614- (insert-before-markers-and-inherit (match-string-no-properties 1 ))
1615- (indent-according-to-mode ))
1616-
1617- ((save-excursion
1618- (forward-line -1 )
1619- (looking-at " $" ))
1620- ; ; The previous line is empty. Uses the default indentation.
1718+ (insert-and-inherit (match-string-no-properties 1 ))
16211719 (indent-according-to-mode ))
16221720
16231721 (t
1624- ; ; Uses the prefix of the previous line.
1625- (insert-before-markers-and-inherit
1626- (save-excursion
1627- (forward-line -1 )
1628- (looking-at " \\ s *" )
1629- (match-string-no-properties 0 )))))
1630-
1631- ; ; Cleans up the previous line.
1632- (save-excursion
1633- (forward-line 0 )
1634- (backward-char )
1635- (delete-horizontal-space ))
1722+ ; ; Uses the default indentation.
1723+ (indent-according-to-mode )))
16361724
16371725 ; ; Closes incomplete multiline comment.
16381726 (when (and swift-mode:auto-close-multiline-comment
1639- (swift-mode:chunk:multiline-comment-p chunk)
1640- (swift-mode:incomplete-comment-p))
1727+ (swift-mode:incomplete-comment-p chunk))
16411728 (save-excursion
16421729 (end-of-line )
16431730 (when comment-multi-line
16441731 (if soft (insert-and-inherit ?\n ) (newline 1 )))
16451732 (insert-and-inherit " */" )
1646- (indent-according-to-mode )))))
1733+ (indent-according-to-mode )))
1734+
1735+ ; ; Make sure the closing delimiter is on its own line.
1736+ (when swift-mode:break-line-before-comment-close
1737+ (save-excursion
1738+ (goto-char comment-beginning-position)
1739+ (when (forward-comment 1 )
1740+ (backward-char )
1741+ (skip-chars-backward " *" )
1742+ (skip-syntax-backward " " )
1743+ (when (not (bolp ))
1744+ (if soft (insert-and-inherit ?\n ) (newline 1 ))
1745+ (indent-according-to-mode )))))))
16471746
16481747(defun swift-mode:post-self-insert ()
16491748 " Miscellaneous logic for electric indentation."
@@ -1656,31 +1755,54 @@ See `indent-new-comment-line' for SOFT."
16561755 (swift-mode:chunk:comment-p (swift-mode:chunk-after))
16571756 (save-excursion (backward-char ) (skip-syntax-backward " " ) (bolp )))
16581757 (when swift-mode:insert-space-after-asterisk-in-comment
1659- (insert-before-markers-and-inherit " " ))
1660- (indent-according-to-mode ))
1758+ (insert-and-inherit " " ))
1759+ (when electric-indent-mode
1760+ (indent-according-to-mode )))
16611761
16621762 ; ; Fixes "* /" at the end of a multiline comment to "*/".
16631763 ((and
1664- (= last-command-event ?/ )
16651764 swift-mode:fix-comment-close
1666- (swift-mode:chunk:comment-p (swift-mode:chunk-after))
1667- (save-excursion
1668- (let ((pos (point )))
1669- (forward-line 0 )
1670- (and
1671- (looking-at " ^\\ s *\\ *\\ s +/" )
1672- (eq (match-end 0 ) pos)
1673- (swift-mode:incomplete-comment-p)))))
1765+ (= last-command-event ?/ )
1766+ (let ((chunk (swift-mode:chunk-after))
1767+ (pos (point )))
1768+ (and
1769+ (swift-mode:chunk:comment-p chunk)
1770+ (save-excursion
1771+ (forward-line 0 )
1772+ (and
1773+ (looking-at " ^\\ s *\\ *\\ s +/" )
1774+ (eq (match-end 0 ) pos)
1775+ (swift-mode:incomplete-comment-p chunk))))))
16741776 (backward-char )
16751777 (delete-horizontal-space )
16761778 (forward-char ))
16771779
16781780 ; ; Indents electrically when ")" is inserted at bol as the end of a string
16791781 ; ; interpolation.
16801782 ((and
1783+ electric-indent-mode
16811784 (= last-command-event ?\) )
1682- (save-excursion (backward-char ) (skip-syntax-backward " " ) (bolp )))
1683- (indent-according-to-mode ))))
1785+ (save-excursion (backward-char ) (skip-syntax-backward " " ) (bolp ))
1786+ (= (swift-mode:chunk:start (swift-mode:chunk-after)) (1- (point ))))
1787+ (indent-according-to-mode ))
1788+
1789+ ; ; Indents electrically after newline inside strings and comments.
1790+ ; ; Unlike `electric-indent-mode' , the previous line is not indented.
1791+ ((and
1792+ electric-indent-mode
1793+ (= last-command-event ?\n ))
1794+ (let ((chunk (swift-mode:chunk-after)))
1795+ (if (swift-mode:chunk:multiline-comment-p chunk)
1796+ (progn
1797+ (delete-horizontal-space )
1798+ (swift-mode:format-multiline-comment-line-after-newline
1799+ chunk
1800+ (not use-hard-newlines)))
1801+ (indent-according-to-mode )))
1802+ (save-excursion
1803+ (forward-line 0 )
1804+ (backward-char )
1805+ (delete-horizontal-space )))))
16841806
16851807(defun swift-mode:highlight-anchor (indentation )
16861808 " Highlight the anchor point of the INDENTATION."
0 commit comments