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

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

[nongnu] elpa/tuareg 04f5ab6be9 3/3: Merge commit 'refs/pull/271/head' o


From: ELPA Syncer
Subject: [nongnu] elpa/tuareg 04f5ab6be9 3/3: Merge commit 'refs/pull/271/head' of github.com:/ocaml/tuareg into elpa/tuareg
Date: Tue, 4 Jan 2022 15:58:25 -0500 (EST)

branch: elpa/tuareg
commit 04f5ab6be9ae1c594bab359819dbaf708ae57fda
Merge: b3e234cd44 402649aaf0
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    Merge commit 'refs/pull/271/head' of github.com:/ocaml/tuareg into 
elpa/tuareg
---
 indent-test.ml  |  13 +++--
 tuareg-tests.el | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tuareg.el       | 106 ++++++++++++++++++++++++++++++++-------
 3 files changed, 246 insertions(+), 23 deletions(-)

diff --git a/indent-test.ml b/indent-test.ml
index 6a63a09255..9e66e855e6 100644
--- a/indent-test.ml
+++ b/indent-test.ml
@@ -44,11 +44,14 @@ let qs1 = {| quoted string |}   (* (issue #24) *)
 let qs2 = {eof| other quoted string   |noteof}  |eof}
 
 (* ocp-indent does it as follows:
-let test1 = with_connection (fun conn ->
-    do_something conn x;
-    ...
-  )
-    toto
+
+   let test1 = with_connection (fun conn ->
+   ␣␣␣␣do_something conn x;
+   ␣␣␣␣...
+   ␣␣)
+   ␣␣␣␣toto
+
+   (space written as ␣ to avoid reindent smashing this comment)
  *)
 let test1 = with_connection (fun conn ->
                 do_something conn x;
diff --git a/tuareg-tests.el b/tuareg-tests.el
index f248320118..429199fed7 100644
--- a/tuareg-tests.el
+++ b/tuareg-tests.el
@@ -652,5 +652,155 @@ the original code."
             (tuareg-test--comment-uncomment-region
              "let f x =\n  g x\n    y\n"))))
 
+(defun tuareg-test--do-at (text pos fun)
+  "Call FUN in TEXT at POS and return the resulting text."
+  (with-temp-buffer
+    (tuareg-mode)
+    (electric-indent-mode 1)
+    (insert text)
+    (goto-char pos)
+    (funcall fun)
+    (buffer-substring-no-properties (point-min) (point-max))))
+
+(defun tuareg-test--line-start (text line)
+  "Position of start of LINE (0-based) in TEXT."
+  (let ((ofs 0))
+    (while (and (> line 0)
+                (let ((nl (string-match-p "\n" text ofs)))
+                  (setq ofs (1+ nl))
+                  (setq line (1- line)))))
+    (1+ ofs)))
+
+(defun tuareg-test--do-at-line (text line fun)
+  "Call FUN in TEXT at start of LINE (0-based) and return the resulting text."
+  (tuareg-test--do-at text (tuareg-test--line-start text line) fun))
+
+(ert-deftest tuareg-indent-comment-text ()
+  ;; Indenting a line should use the indentation of the previous line's text.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (** alpha\n"
+                          "beta\n")
+                  1 #'indent-for-tab-command)
+                 (concat "  (** alpha\n"
+                         "      beta\n")))
+  ;; Tab should indent even at the end of the line.
+  (should (equal (tuareg-test--do-at
+                  (concat "  (** alpha\n"
+                          "beta")
+                  17 #'indent-for-tab-command)
+                 (concat "  (** alpha\n"
+                         "      beta")))
+  ;; An interactive `newline' should indent the new line correctly
+  ;; in Emacs 28 and later.
+  (when (>= emacs-major-version 28)
+    (should (equal (tuareg-test--do-at
+                    "(** alpha"
+                    10 (lambda () (call-interactively #'newline)))
+                   (concat "(** alpha\n"
+                           "    "))))
+  ;; The previous line's indentation should be respected and preserved.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (* alpha\n"
+                          "       beta\n"
+                          " gamma\n")
+                  2 #'indent-for-tab-command)
+                 (concat "  (* alpha\n"
+                         "       beta\n"
+                         "       gamma\n")))
+  ;; Use the previous nonempty line for indentation.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (* alpha\n"
+                          "      beta\n"
+                          "  \n"
+                          " gamma\n")
+                  3 #'indent-for-tab-command)
+                 (concat "  (* alpha\n"
+                         "      beta\n"
+                         "  \n"
+                         "      gamma\n")))
+  ;; Indent text after @-tags in doc comments by 2 more spaces.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (** alpha\n"
+                          "        @param beta\n"
+                          " gamma\n")
+                  2 #'indent-for-tab-command)
+                 (concat "  (** alpha\n"
+                         "        @param beta\n"
+                         "          gamma\n")))
+  ;; An @-tag starts a new paragraph.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (** alpha\n"
+                          "        @param beta\n"
+                          " @return gamma\n")
+                  2 #'indent-for-tab-command)
+                 (concat "  (** alpha\n"
+                         "        @param beta\n"
+                         "        @return gamma\n")))
+  ;; @-tags are not special in plain comments.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (* alpha\n"
+                          "        @param beta\n"
+                          " gamma\n")
+                  2 #'indent-for-tab-command)
+                 (concat "  (* alpha\n"
+                         "        @param beta\n"
+                         "        gamma\n")))
+  ;; Filling one paragraph does not affect other paragraphs.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (* alpha beta gamma\n"
+                          "delta epsilon\n"
+                          "\n"
+                          "zeta eta theta iota kappa *)\n")
+                  1 (lambda () (let ((fill-column 17))
+                                 (funcall (local-key-binding (kbd "M-q"))))))
+                 (concat "  (* alpha beta\n"
+                         "     gamma delta\n"
+                         "     epsilon\n"
+                          "\n"
+                          "zeta eta theta iota kappa *)\n")))
+  ;; Filling affects the preceding paragraph, not the succeeding.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (* alpha beta gamma\n"
+                          "delta epsilon\n"
+                          "\n"
+                          "zeta eta theta iota kappa *)\n")
+                  2 (lambda () (let ((fill-column 17))
+                                 (funcall (local-key-binding (kbd "M-q"))))))
+                 (concat "  (* alpha beta\n"
+                         "     gamma delta\n"
+                         "     epsilon\n"
+                          "\n"
+                          "zeta eta theta iota kappa *)\n")))
+
+  ;; A paragraph's indentation is determined by its first line.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (* alpha\n"
+                          "     beta\n"
+                          "\n"
+                          "       gamma\n"
+                          "delta epsilon zeta eta *)\n")
+                  3 (lambda () (let ((fill-column 19))
+                                 (funcall (local-key-binding (kbd "M-q"))))))
+                  (concat "  (* alpha\n"
+                          "     beta\n"
+                          "\n"
+                          "       gamma delta\n"
+                          "       epsilon zeta\n"
+                          "       eta *)\n")))
+  ;; @-tags separate paragraphs in doc comments.
+  (should (equal (tuareg-test--do-at-line
+                  (concat "  (** alpha\n"
+                          "      beta\n"
+                          "       @param gamma delta epsilon\n"
+                          "       @param zeta eta theta iota\n")
+                  4 (lambda () (let ((fill-column 25))
+                                 (funcall (local-key-binding (kbd "M-q"))))))
+                  (concat "  (** alpha\n"
+                          "      beta\n"
+                          "       @param gamma delta epsilon\n"
+                          "       @param zeta eta\n"
+                          "         theta iota\n")))
+  )
+
 
 (provide 'tuareg-tests)
diff --git a/tuareg.el b/tuareg.el
index 8589e88b90..7c7ef4c66d 100644
--- a/tuareg.el
+++ b/tuareg.el
@@ -2885,24 +2885,51 @@ This function moves the point."
 (defun tuareg--fill-comment ()
   "Assumes the point is inside a comment and justify it.
 This function moves the point."
-  (let* ((start (set-marker (make-marker) (nth 8 (syntax-ppss))))
-         (end (make-marker))
-         fill-prefix
-         (use-hard-newlines t))
-    (goto-char (marker-position start))
-    (indent-according-to-mode)
-    (setq fill-prefix (make-string (+ 3 (current-column)) ?\ ))
-    (forward-comment 1)
-    (set-marker end (point))
-    (goto-char (marker-position start))
-    (let ((e (marker-position end)))
-      (while (re-search-forward "\n\n" e t)
-        (put-text-property (match-beginning 0) (match-end 0) 'hard 't)))
-    (fill-region start end)
-    (remove-text-properties (marker-position start) (marker-position end)
-                            '(hard))
-    (set-marker start nil)
-    (set-marker end nil)))
+  (let* ((com-start (nth 8 (syntax-ppss)))
+         content-start
+         com-end
+         in-doc-comment
+         par-start
+         par-end)
+    (save-excursion
+      (goto-char com-start)
+      (setq content-start (and (looking-at comment-start-skip)
+                               (match-end 0)))
+      (setq in-doc-comment (looking-at-p (rx "(**" (not (in "*")))))
+      (forward-comment 1)
+      (setq com-end (point)))
+
+    ;; In doc comments, let @tags start a paragraph.
+    (let ((paragraph-start
+           (if in-doc-comment
+               (concat paragraph-start
+                       "\\|"
+                       (rx (* (in " \t")) "@" (+ (in "a-z")) symbol-end))
+             paragraph-start)))
+      (save-restriction
+        (narrow-to-region content-start com-end)
+        (save-excursion
+          (skip-chars-forward " \t")
+          (backward-paragraph)
+          (skip-chars-forward " \t\n")
+          (setq par-start (point))
+          (forward-paragraph)
+          (setq par-end (point))))
+
+      ;; Set `fill-prefix' to preserve the indentation of the start of the
+      ;; paragraph, assuming that is what the user wants.
+      (let ((fill-prefix
+             (save-excursion
+               (goto-char par-start)
+               (let ((col
+                      (if (and in-doc-comment
+                               (looking-at-p
+                                (rx "@" (+ (in "a-z")) symbol-end)))
+                          ;; Indent two spaces under @tag.
+                          (+ 2 (current-column))
+                        (current-column))))
+                 (make-string col ?\s)))))
+        (fill-region-as-paragraph par-start par-end)))))
 
 (defun tuareg-indent-phrase ()
   "Depending of the context: justify and indent a comment,
@@ -3121,6 +3148,47 @@ file outside _build? "))
          (t (list here-beg here-end here-beg here-end t))))))
    (t (funcall orig-fun))))
 
+(defun tuareg--indent-line-inside-comment ()
+  "Indent the current line if it is inside a comment."
+  (let ((ppss (syntax-ppss)))
+    (and (nth 4 ppss)
+         (let ((indent-col
+                (save-excursion
+                  (let* ((com-start (nth 8 ppss))
+                         (in-doc-comment
+                          (save-excursion
+                            (goto-char com-start)
+                            (looking-at-p (rx "(**" (not (in "*"))))))
+                         tag-starts-line)
+                    ;; Use the indentation of the previous nonempty line.
+                    ;; If we are in a doc comment and that line
+                    ;; starts with an @tag, and the current line
+                    ;; doesn't, then indent to after the @tag.
+                    (goto-char (max com-start (line-beginning-position)))
+                    (setq tag-starts-line
+                          (and in-doc-comment
+                               (looking-at-p
+                                (rx (* (in " \t"))
+                                    "@" (+ (in "a-z")) symbol-end))))
+                    (skip-chars-backward " \t\n" com-start)
+                    (goto-char (max com-start (line-beginning-position)))
+                    (when (looking-at (rx "(*" (* "*")))
+                      (goto-char (match-end 0)))
+                    (skip-chars-forward " \t")
+                    (when (and in-doc-comment
+                               (not tag-starts-line)
+                               (looking-at-p (rx "@" (+ (in "a-z")) " ")))
+                      (forward-char 2)))
+                  (current-column))))
+           (indent-line-to indent-col)
+           t))))
+
+(defun tuareg--indent-line (orig-fun)
+  (let ((res (funcall orig-fun)))
+    (if (eq res 'noindent)
+        (tuareg--indent-line-inside-comment)
+      res)))
+
 (defun tuareg--common-mode-setup ()
   (setq-local syntax-propertize-function #'tuareg-syntax-propertize)
   (setq-local parse-sexp-ignore-comments t)
@@ -3133,6 +3201,8 @@ file outside _build? "))
     ;; hasn't provided any alternative so far :-(
     (add-function :before (local 'smie--hanging-eolp-function)
                   #'tuareg--hanging-eolp-advice))
+  (add-function :around (local 'indent-line-function)
+                #'tuareg--indent-line)
   (add-hook 'smie-indent-functions #'tuareg-smie--args nil t)
   (add-hook 'smie-indent-functions #'tuareg-smie--inside-string nil t)
   (setq-local add-log-current-defun-function #'tuareg-current-fun-name)



reply via email to

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