[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/go-mode b212a73 1/2: Replace our fill-paragraph code with
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/go-mode b212a73 1/2: Replace our fill-paragraph code with a modified copy from rust-mode |
Date: |
Wed, 15 Dec 2021 05:57:58 -0500 (EST) |
branch: elpa/go-mode
commit b212a73c21a8b806f9764004397c1d03eb0b2e10
Author: Dominik Honnef <dominik@honnef.co>
Commit: Dominik Honnef <dominik@honnef.co>
Replace our fill-paragraph code with a modified copy from rust-mode
With no offense to the author of the original code, the copy from
rust-mode, after some slight modifications, works more reliably than
what we had before and is (somewhat) easier to understand.
fill-region no longer locks up, and multi-line strings can be
reformatted somewhat (because we no longer prevent formatting of
non-comments). In the future we may want to improve upon this to
handle strings specially, and prevent reflowing code, much like
cc-mode does.
Closes gh-390
Updates gh-386
---
go-mode.el | 251 +++++++++++++++++++++++++----------------
test/go-fill-paragraph-test.el | 22 +---
2 files changed, 159 insertions(+), 114 deletions(-)
diff --git a/go-mode.el b/go-mode.el
index 21d01ff..11c5bef 100644
--- a/go-mode.el
+++ b/go-mode.el
@@ -762,97 +762,6 @@ case keyword. It returns nil for the case line itself."
(replace-regexp-in-string "/\\*" " "
(match-string-no-properties 0))))))
-(defun go--fill-paragraph (&rest args)
- "Wrap fill-paragraph to set custom fill-prefix."
- (let ((fill-prefix (go--fill-prefix))
- (fill-paragraph-function nil))
- (apply 'fill-paragraph args)))
-
-(defun go--empty-line-p ()
- (looking-at "[[:space:]]*$"))
-
-(defun go--boring-comment-p ()
- "Return non-nil if we are looking at a boring comment.
-
-A boring comment is a comment with no content. For example:
-
-//////// ; boring
-// hello
-//////// ; boring
-
-/* ; boring
- hello
-*/ ; boring
-"
- (or
- (looking-at-p "[[:space:]]*//+[[:space:]]*$")
- (looking-at-p "[[:space:]]*\\(?:/\\*+\\|\\*/+\\)[[:space:]]*$")))
-
-(defun go--interesting-comment-p ()
- "Return non-nil if we are looking at an interesting comment.
-
-An interesting comment is one that contains content other than
-comment starter/closer characters."
-
- (if (go-in-comment-p)
- (and
- (not (go--empty-line-p))
- (not (looking-at-p "[[:space:]]*\\*/")))
- (and
- (looking-at go--comment-start-regexp)
- (not (go--boring-comment-p)))))
-
-(defun go--fill-forward-paragraph (&optional arg)
- "forward-paragraph like function used for fill-paragraph.
-
-This function is key for making fill-paragraph do the right
-thing for comments."
- (beginning-of-line)
- (let* ((arg (or arg 1))
- (single (if (> arg 0) 1 -1))
- (done nil))
- (while (and (not done) (not (zerop arg)))
- ;; If we are moving backwards and aren't currently looking at a
- ;; comment, move back one line. This is to make sure
- ;; (go--fill-forward-paragraph -1) always works properly as the
- ;; inverse of (go--fill-forward-paragraph 1).
- (when (and
- (= single -1)
- (not (go-in-comment-p))
- (not (looking-at-p go--comment-start-regexp)))
- (forward-line -1))
-
- ;; Skip empty lines and comment lines with no content.
- (while (and
- (or (go--empty-line-p) (go--boring-comment-p))
- (zerop (forward-line single))))
-
- (let (saw-comment)
- ;; Skip comment lines that have content.
- (while (and
- (go--interesting-comment-p)
- (zerop (forward-line single)))
- (setq saw-comment t))
-
- (if (not saw-comment)
- (progn
- ;; In fill-region case user may have selected a region
- ;; with non-comments. fill-region will loop forever
- ;; until it makes it to the end of the region, so just
- ;; fall back to `forward-paragraph' so we make progress.
- (when mark-active
- (setq arg (forward-paragraph arg)))
- (setq done t))
- ;; If we are going backwards, move forward one line so we
- ;; are on the first interesting line of the comment. Note
- ;; that the current line may already be interesting if we
- ;; are at the beginning of the buffer.
- (when (and (= single -1) (not (go--interesting-comment-p)))
- (forward-line 1))
- (cl-decf arg single))))
- arg))
-
-
(defun go--open-paren-position ()
"Return non-nil if point is between '(' and ')'.
@@ -879,6 +788,10 @@ The return value is the position of the opening paren."
(go--multiline-comment-indent)
(go--indentation-at-point))))
+;; It's unfortunate that the user cannot reindent the current line to
+;; align with the previous line; however, if they could, then people
+;; who use reindent-then-newline-and-indent wouldn't be able to
+;; explicitly indent lines inside comments.
(defun go--multiline-comment-indent ()
"Return the appropriate indent inside multiline comment.
@@ -1901,10 +1814,25 @@ with goflymake (see URL
`https://github.com/dougm/goflymake'), gocode
(set (make-local-variable 'comment-end) "")
(set (make-local-variable 'comment-use-syntax) t)
(set (make-local-variable 'comment-start-skip) "\\(//+\\|/\\*+\\)\\s *")
- (set (make-local-variable 'comment-region-function) 'go--comment-region)
+ (set (make-local-variable 'comment-region-function) #'go--comment-region)
+ ;; Set comment-multi-line to t so that comment-indent-new-line
+ ;; doesn't use one /* */ per line. Thanks to comment-use-syntax,
+ ;; Emacs is smart enough to still insert new // for single-line
+ ;; comments.
+ (set (make-local-variable 'comment-multi-line) t)
(set (make-local-variable 'beginning-of-defun-function)
#'go-beginning-of-defun)
(set (make-local-variable 'end-of-defun-function) #'go-end-of-defun)
+ (setq-local paragraph-start
+ (concat "[[:space:]]*\\(?:"
+ comment-start-skip
+ "\\|\\*/?[[:space:]]*\\|\\)$"))
+ (setq-local paragraph-separate paragraph-start)
+ (setq-local fill-paragraph-function #'go-fill-paragraph)
+ (setq-local fill-forward-paragraph-function #'go--fill-forward-paragraph)
+ (setq-local adaptive-fill-function #'go--find-fill-prefix)
+ (setq-local adaptive-fill-first-line-regexp "")
+ (setq-local comment-line-break-function #'go--comment-indent-new-line)
(set (make-local-variable 'parse-sexp-lookup-properties) t)
(set (make-local-variable 'syntax-propertize-function)
#'go-propertize-syntax)
@@ -1918,10 +1846,6 @@ with goflymake (see URL
`https://github.com/dougm/goflymake'), gocode
(set (make-local-variable 'go-dangling-cache) (make-hash-table :test 'eql))
(add-hook 'before-change-functions #'go--reset-dangling-cache-before-change
t t)
- (set (make-local-variable 'adaptive-fill-function) #'go--fill-prefix)
- (set (make-local-variable 'fill-paragraph-function) #'go--fill-paragraph)
- (set (make-local-variable 'fill-forward-paragraph-function)
#'go--fill-forward-paragraph)
-
;; ff-find-other-file
(setq ff-other-file-alist 'go-other-file-alist)
@@ -3063,6 +2987,141 @@ If BUFFER, return the number of characters in that
buffer instead."
(concat remote "/tmp")
temporary-file-directory)))))
+
+;; The following functions were copied (and modified) from rust-mode.el.
+;;
+;; Copyright (c) 2015 The Rust Project Developers
+;;
+;; Permission is hereby granted, free of charge, to any
+;; person obtaining a copy of this software and associated
+;; documentation files (the "Software"), to deal in the
+;; Software without restriction, including without
+;; limitation the rights to use, copy, modify, merge,
+;; publish, distribute, sublicense, and/or sell copies of
+;; the Software, and to permit persons to whom the Software
+;; is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice
+;; shall be included in all copies or substantial portions
+;; of the Software.
+
+(defun go--fill-prefix-for-comment-start (line-start)
+ "Determine what to use for `fill-prefix' based on the text at LINE-START."
+ (let ((result
+ ;; Replace /* with same number of spaces
+ (replace-regexp-in-string
+ "\\(?:/\\*+?\\)[!*]?"
+ (lambda (s)
+ (let ((offset (if (eq t
+ (compare-strings "/*" nil nil
+ s
+ (- (length s) 2)
+ (length s)))
+ 1 2)))
+ (make-string (1+ (- (length s) offset)) ?\x20)))
+ line-start)))
+ ;; Make sure we've got at least one space at the end
+ (if (not (= (aref result (- (length result) 1)) ?\x20))
+ (setq result (concat result " ")))
+ result))
+
+(defun go--in-comment-paragraph (body)
+ ;; We might move the point to fill the next comment, but we don't want it
+ ;; seeming to jump around on the user
+ (save-excursion
+ ;; If we're outside of a comment, with only whitespace and then a comment
+ ;; in front, jump to the comment and prepare to fill it.
+ (when (not (go-in-comment-p))
+ (beginning-of-line)
+ (when (looking-at (concat "[[:space:]\n]*" comment-start-skip))
+ (goto-char (match-end 0))))
+
+ ;; If we're at the beginning of a comment paragraph with nothing but
+ ;; whitespace til the next line, jump to the next line so that we use the
+ ;; existing prefix to figure out what the new prefix should be, rather than
+ ;; inferring it from the comment start.
+ (while (save-excursion
+ (end-of-line)
+ (and (go-in-comment-p)
+ (save-excursion
+ (beginning-of-line)
+ (looking-at paragraph-start))
+ (looking-at "[[:space:]]*$")
+ (nth 4 (syntax-ppss (line-beginning-position 2)))))
+ (goto-char (line-beginning-position 2)))
+
+ ;; If we're on the last line of a multiline-style comment that started
+ ;; above, back up one line so we don't mistake the * of the */ that ends
+ ;; the comment for a prefix.
+ (when (save-excursion
+ (and (nth 4 (syntax-ppss (line-beginning-position 1)))
+ (looking-at "[[:space:]]*\\*/")))
+ (goto-char (line-end-position 0)))
+ (funcall body)))
+
+(defun go--with-comment-fill-prefix (body)
+ (let*
+ ((line-string (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position)))
+ (line-comment-start
+ (when (go-in-comment-p)
+ (cond
+ ;; If we're inside the comment and see a * prefix, use it
+ ((string-match "^\\([[:space:]]*\\*+[[:space:]]*\\)"
+ line-string)
+ (match-string 1 line-string))
+ ;; If we're at the start of a comment, figure out what prefix
+ ;; to use for the subsequent lines after it
+ ((string-match (concat "[[:space:]]*" comment-start-skip)
line-string)
+ (go--fill-prefix-for-comment-start
+ (match-string 0 line-string))))))
+ (fill-prefix
+ (or line-comment-start
+ fill-prefix)))
+ (funcall body)))
+
+(defun go--find-fill-prefix ()
+ (go--in-comment-paragraph
+ (lambda ()
+ (go--with-comment-fill-prefix
+ (lambda ()
+ fill-prefix)))))
+
+(defun go-fill-paragraph (&rest args)
+ "Special wrapping for `fill-paragraph'.
+This handles multi-line comments with a * prefix on each line."
+ (go--in-comment-paragraph
+ (lambda ()
+ (go--with-comment-fill-prefix
+ (lambda ()
+ (let
+ ((fill-paragraph-function
+ (if (not (eq fill-paragraph-function 'go-fill-paragraph))
+ fill-paragraph-function))
+ (fill-paragraph-handle-comment t))
+ (apply 'fill-paragraph args)
+ t))))))
+
+(defun go--do-auto-fill (&rest args)
+ "Special wrapping for `do-auto-fill'.
+This handles multi-line comments with a * prefix on each line."
+ (go--with-comment-fill-prefix
+ (lambda ()
+ (apply 'do-auto-fill args)
+ t)))
+
+(defun go--fill-forward-paragraph (arg)
+ ;; This is to work around some funny behavior when a paragraph separator is
+ ;; at the very top of the file and there is a fill prefix.
+ (let ((fill-prefix nil)) (forward-paragraph arg)))
+
+(defun go--comment-indent-new-line (&optional arg)
+ (go--with-comment-fill-prefix
+ (lambda () (comment-indent-new-line arg))))
+
+
+
(provide 'go-mode)
;;; go-mode.el ends here
diff --git a/test/go-fill-paragraph-test.el b/test/go-fill-paragraph-test.el
index 9d23aab..6a4a830 100644
--- a/test/go-fill-paragraph-test.el
+++ b/test/go-fill-paragraph-test.el
@@ -25,21 +25,6 @@ represents point and mark to test the region based
fill-paragraph."
(call-interactively 'fill-paragraph)
(should (string= (buffer-string) expected)))))
-(ert-deftest go--fill-paragraph-no-comment ()
- (go--should-fill
- "
-func main() {
-<>
- reallyLongLineButThereAreNoCommentsHere() +
reallyLongLineButThereAreNoCommentsHere()
-}"
-
- "
-func main() {
-
- reallyLongLineButThereAreNoCommentsHere() +
reallyLongLineButThereAreNoCommentsHere()
-}"
- ))
-
(ert-deftest go--fill-paragraph-single ()
(go--should-fill
"
@@ -148,7 +133,8 @@ func main() {
func main() {
/*
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
- do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua.
*/
}"
))
@@ -171,8 +157,8 @@ func main() {
(go--should-fill
"
func main() {
-<> /////////////////////
- // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
+ /////////////////////
+<> // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
/////////////////////
}"