From e7d5af8ec780adf2acf46bb017732cae02a6a867 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Fri, 30 Aug 2013 16:58:43 -0400 Subject: [PATCH 1/9] Fix glitches with struct field aligned indents --- src/etc/emacs/rust-mode.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index 92b85247e48..e8cfd05a4f0 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -85,10 +85,10 @@ (not (looking-at "[[:space:]]*\\(?://.*\\)?$")))) (+ 1 (current-column))) ;; Check for fields on the same line as the open curly brace: - ((looking-at "{[[:blank:]]*[^}\n]*,[[:space:]]*$") + ((looking-at "{[[:space:]]*[^\n]*,[[:space:]]*$") (progn (forward-char) - (forward-to-word 1) + (when (looking-at "[[:space:]]") (forward-to-word 1)) (current-column))) (t (progn (goto-char pt) From 1c527dfcd466d9b5ea75fe199c364837298a4278 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 5 Sep 2013 22:25:41 -0400 Subject: [PATCH 2/9] Indent correctly after opening square bracket --- src/etc/emacs/rust-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index e8cfd05a4f0..e45cec94797 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -100,7 +100,7 @@ (beginning-of-line) (rust-rewind-irrelevant) (end-of-line) - (if (looking-back "[,;{}(][[:space:]]*\\(?://.*\\)?") + (if (looking-back "[[,;{}(][[:space:]]*\\(?://.*\\)?") (* rust-indent-offset level) (back-to-indentation) (if (looking-at "#") From 9ef0b9c0d6180f0e5023b29ac57835e6e75517d0 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 5 Sep 2013 22:26:30 -0400 Subject: [PATCH 3/9] Allow indenting to align struct fields after curly brace --- src/etc/emacs/rust-mode.el | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index e45cec94797..ff9119250cd 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -45,6 +45,16 @@ (if (/= starting (point)) (rust-rewind-irrelevant)))) +(defun rust-first-indent-after-brace () + (save-excursion + (forward-char) + (if (looking-at "[[:blank:]]*\\(?://.*\\)?$") + ;; We don't want to indent out to the open bracket if the + ;; open bracket ends the line + (* rust-indent-offset (rust-paren-level)) + (when (looking-at "[[:space:]]") (forward-to-word 1)) + (current-column)))) + (defun rust-mode-indent-line () (interactive) (let ((indent @@ -58,7 +68,7 @@ ;; A closing brace is 1 level unindended ((looking-at "}") (* rust-indent-offset (- level 1))) - ; Doc comments in /** style with leading * indent to line up the *s + ;; Doc comments in /** style with leading * indent to line up the *s ((and (nth 4 (syntax-ppss)) (looking-at "*")) (+ 1 (* rust-indent-offset level))) @@ -75,22 +85,9 @@ (let ((pt (point))) (rust-rewind-irrelevant) (backward-up-list) - (cond - ((and - (looking-at "[[(]") - ; We don't want to indent out to the open bracket if the - ; open bracket ends the line - (save-excursion - (forward-char) - (not (looking-at "[[:space:]]*\\(?://.*\\)?$")))) - (+ 1 (current-column))) - ;; Check for fields on the same line as the open curly brace: - ((looking-at "{[[:space:]]*[^\n]*,[[:space:]]*$") + (if (looking-at "[[({]") + (rust-first-indent-after-brace) (progn - (forward-char) - (when (looking-at "[[:space:]]") (forward-to-word 1)) - (current-column))) - (t (progn (goto-char pt) (back-to-indentation) (if (looking-at "\\") @@ -105,7 +102,7 @@ (back-to-indentation) (if (looking-at "#") (* rust-indent-offset level) - (* rust-indent-offset (+ 1 level))))))))))) + (* rust-indent-offset (+ 1 level)))))))))) ;; Otherwise we're in a column-zero definition (t 0)))))) From 76e95a02647cd46494173839d574403bf1ed699b Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 5 Sep 2013 22:23:16 -0400 Subject: [PATCH 4/9] Indent return type to align with arguments --- src/etc/emacs/rust-mode.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index ff9119250cd..d7c4142352e 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -62,8 +62,11 @@ (back-to-indentation) (let ((level (rust-paren-level))) (cond - ;; A function return type is 1 level indented - ((looking-at "->") (* rust-indent-offset (+ level 1))) + ;; A function return type is indented to the corresponding function arguments + ((looking-at "->") + (save-excursion + (backward-list) + (rust-first-indent-after-brace))) ;; A closing brace is 1 level unindended ((looking-at "}") (* rust-indent-offset (- level 1))) From 1ac7c5cc5a8589061edca64f0dead59787265e9c Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Tue, 3 Sep 2013 23:54:39 -0400 Subject: [PATCH 5/9] Add custom group for rust-mode --- src/etc/emacs/rust-mode.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index d7c4142352e..8651fb6c550 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -30,8 +30,11 @@ table)) +(defgroup rust-mode nil "Support for Rust code.") + (defcustom rust-indent-offset 4 - "*Indent Rust code by this number of spaces.") + "*Indent Rust code by this number of spaces." + :group 'rust-mode) (defun rust-paren-level () (nth 0 (syntax-ppss))) (defun rust-in-str-or-cmnt () (nth 8 (syntax-ppss))) @@ -215,6 +218,7 @@ ;;;###autoload (define-derived-mode rust-mode rust-parent-mode "Rust" "Major mode for Rust code." + :group 'rust-mode ;; Basic syntax (set-syntax-table rust-mode-syntax-table) From 377b2c77e4bf738c7bfb6d1d4d19d45c0b79d5c1 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 5 Sep 2013 22:38:37 -0400 Subject: [PATCH 6/9] Add paragraph fill and auto-fill for multi-line comments --- src/etc/emacs/rust-mode.el | 124 ++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index 8651fb6c550..e809a3431eb 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -209,6 +209,114 @@ collect `(,(rust-re-item-def item) 1 ,face)))) +(defun rust-fill-prefix-for-comment-start (line-start) + "Determine what to use for `fill-prefix' based on what is at the beginning of a line." + (let ((result + ;; Replace /* with same number of spaces + (replace-regexp-in-string + "\\(?:/\\*+\\)[!*]" + (lambda (s) + ;; We want the * to line up with the first * of the comment start + (concat (make-string (- (length s) 2) ?\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 rust-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 (nth 4 (syntax-ppss))) + (beginning-of-line) + (when (looking-at (concat "[[:space:]\n]*" comment-start-skip)) + (goto-char (match-end 0)))) + + ;; We need this when we're moving the point around and then checking syntax + ;; while doing paragraph fills, because the cache it uses isn't always + ;; invalidated during this. + (syntax-ppss-flush-cache 1) + ;; 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. + (let ((next-bol (line-beginning-position 2))) + (while (save-excursion + (end-of-line) + (syntax-ppss-flush-cache 1) + (and (nth 4 (syntax-ppss)) + (save-excursion + (beginning-of-line) + (looking-at paragraph-start)) + (looking-at "[[:space:]]*$") + (nth 4 (syntax-ppss next-bol)))) + (goto-char next-bol))) + + (syntax-ppss-flush-cache 1) + ;; 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 rust-with-comment-fill-prefix (body) + (let* + ((line-string (buffer-substring-no-properties + (line-beginning-position) (line-end-position))) + (line-comment-start + (when (nth 4 (syntax-ppss)) + (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) + (rust-fill-prefix-for-comment-start + (match-string 0 line-string)))))) + (fill-prefix + (or line-comment-start + fill-prefix))) + (funcall body))) + +(defun rust-find-fill-prefix () + (rust-with-comment-fill-prefix (lambda () fill-prefix))) + +(defun rust-fill-paragraph (&rest args) + "Special wrapping for `fill-paragraph' to handle multi-line comments with a * prefix on each line." + (rust-in-comment-paragraph + (lambda () + (rust-with-comment-fill-prefix + (lambda () + (let + ((fill-paragraph-function + (if (not (eq fill-paragraph-function 'rust-fill-paragraph)) + fill-paragraph-function))) + (apply 'fill-paragraph args) + t)))))) + +(defun rust-do-auto-fill (&rest args) + "Special wrapping for `do-auto-fill' to handle multi-line comments with a * prefix on each line." + (rust-with-comment-fill-prefix + (lambda () + (apply 'do-auto-fill args) + t))) + +(defun rust-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 rust-comment-indent-new-line (&optional arg) + (rust-with-comment-fill-prefix + (lambda () (comment-indent-new-line arg)))) ;; For compatibility with Emacs < 24, derive conditionally (defalias 'rust-parent-mode @@ -234,7 +342,21 @@ ;; Misc (set (make-local-variable 'comment-start) "// ") (set (make-local-variable 'comment-end) "") - (set (make-local-variable 'indent-tabs-mode) nil)) + (set (make-local-variable 'indent-tabs-mode) nil) + + ;; Allow paragraph fills for comments + (set (make-local-variable 'comment-start-skip) + "\\(?://[/!]*\\|/\\*[*!]?\\)[[:space:]]*") + (set (make-local-variable 'paragraph-start) + (concat "[[:space:]]*\\(?:" comment-start-skip "\\|\\*/?[[:space:]]*\\|\\)$")) + (set (make-local-variable 'paragraph-separate) paragraph-start) + (set (make-local-variable 'normal-auto-fill-function) 'rust-do-auto-fill) + (set (make-local-variable 'fill-paragraph-function) 'rust-fill-paragraph) + (set (make-local-variable 'fill-forward-paragraph-function) 'rust-fill-forward-paragraph) + (set (make-local-variable 'adaptive-fill-function) 'rust-find-fill-prefix) + (set (make-local-variable 'comment-multi-line) t) + (set (make-local-variable 'comment-line-break-function) 'rust-comment-indent-new-line) + ) ;;;###autoload From fcf18786b4c37972d9220bfb8bbe6a4875433faf Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 5 Sep 2013 23:02:37 -0400 Subject: [PATCH 7/9] Add ERT tests --- src/etc/emacs/README.md | 6 + src/etc/emacs/run_rust_emacs_tests.sh | 3 + src/etc/emacs/rust-mode-tests.el | 380 ++++++++++++++++++++++++++ 3 files changed, 389 insertions(+) create mode 100755 src/etc/emacs/run_rust_emacs_tests.sh create mode 100644 src/etc/emacs/rust-mode-tests.el diff --git a/src/etc/emacs/README.md b/src/etc/emacs/README.md index 508ac7f1af2..63fbe1f681c 100644 --- a/src/etc/emacs/README.md +++ b/src/etc/emacs/README.md @@ -68,6 +68,12 @@ marking, press x, and ELPA will install the packages for you (under * or using M-x package-install rust-mode +### Tests via ERT + +The file `rust-mode-tests.el` contains tests that can be run via ERT. You can +use `run_rust_emacs_tests.sh` to run them in batch mode, if emacs is somewhere +in your `$PATH`. + ### Known bugs * Combining `global-whitespace-mode` and `rust-mode` is generally glitchy. diff --git a/src/etc/emacs/run_rust_emacs_tests.sh b/src/etc/emacs/run_rust_emacs_tests.sh new file mode 100755 index 00000000000..afb98fde7b0 --- /dev/null +++ b/src/etc/emacs/run_rust_emacs_tests.sh @@ -0,0 +1,3 @@ +# This runs the test for emacs rust-mode. +# It must be possible to find emacs via PATH. +emacs -batch -l rust-mode.el -l rust-mode-tests.el -f ert-run-tests-batch-and-exit diff --git a/src/etc/emacs/rust-mode-tests.el b/src/etc/emacs/rust-mode-tests.el new file mode 100644 index 00000000000..a7cb2613b9a --- /dev/null +++ b/src/etc/emacs/rust-mode-tests.el @@ -0,0 +1,380 @@ +;;; rust-mode-tests.el --- ERT tests for rust-mode.el + +(require 'rust-mode) +(require 'ert) +(require 'cl) + +(setq rust-test-fill-column 32) + +(defun rust-compare-code-after-manip (original point-pos manip-func expected got) + (equal expected got)) + +(defun rust-test-explain-bad-manip (original point-pos manip-func expected got) + (if (equal expected got) + nil + (list + ;; The (goto-char) and (insert) business here is just for + ;; convenience--after an error, you can copy-paste that into emacs eval to + ;; insert the bare strings into a buffer + "Rust code was manipulated wrong after:" + `(insert ,original) + `(goto-char ,point-pos) + 'expected `(insert ,expected) + 'got `(insert ,got) + (loop for i from 0 to (max (length original) (length expected)) + for oi = (if (< i (length got)) (elt got i)) + for ei = (if (< i (length expected)) (elt expected i)) + while (equal oi ei) + finally return `(first-difference-at + (goto-char ,(+ 1 i)) + expected ,(char-to-string ei) + got ,(char-to-string oi)))))) +(put 'rust-compare-code-after-manip 'ert-explainer + 'rust-test-explain-bad-manip) + +(defun rust-test-manip-code (original point-pos manip-func expected) + (with-temp-buffer + (rust-mode) + (insert original) + (goto-char point-pos) + (funcall manip-func) + (should (rust-compare-code-after-manip + original point-pos manip-func expected (buffer-string))))) + +(defun test-fill-paragraph (unfilled expected &optional start-pos end-pos) + "We're going to run through many scenarios here--the point should be able to be anywhere from the start-pos (defaults to 1) through end-pos (defaults to the length of what was passed in) and (fill-paragraph) should return the same result. + +Also, the result should be the same regardless of whether the code is at the beginning or end of the file. (If you're not careful, that can make a difference.) So we test each position given above with the passed code at the beginning, the end, neither and both. So we do this a total of (end-pos - start-pos)*4 times. Oy." + (let* ((start-pos (or start-pos 1)) + (end-pos (or end-pos (length unfilled))) + (padding "\n \n") + (padding-len (length padding))) + (loop + for pad-at-beginning from 0 to 1 + for pad-at-end from 0 to 1 + with padding-beginning = (if (= 0 pad-at-beginning) "" padding) + with padding-end = (if (= 0 pad-at-end) "" padding) + with padding-adjust = (* padding-len pad-at-beginning) + with padding-beginning = (if (= 0 pad-at-beginning) "" padding) + with padding-end = (if (= 0 pad-at-end) "" padding) + for pos from (if (= 1 start-pos) 1 (+ padding-adjust start-pos)) to (+ end-pos padding-adjust) + do (rust-test-manip-code + (concat padding-beginning unfilled padding-end) + pos + (lambda () + (let ((fill-column rust-test-fill-column)) + (fill-paragraph))) + (concat padding-beginning expected padding-end))))) + +(ert-deftest fill-paragraph-top-level-multi-line-style-doc-comment-second-line () + (test-fill-paragraph + "/** + * This is a very very very very very very very long string + */" + "/** + * This is a very very very very + * very very very long string + */")) + + +(ert-deftest fill-paragraph-top-level-multi-line-style-doc-comment-first-line () + (test-fill-paragraph + "/** This is a very very very very very very very long string + */" + "/** This is a very very very + * very very very very long + * string + */")) + +(ert-deftest fill-paragraph-multi-paragraph-multi-line-style-doc-comment () + (let + ((multi-paragraph-unfilled + "/** + * This is the first really really really really really really really long paragraph + * + * This is the second really really really really really really long paragraph + */")) + (test-fill-paragraph + multi-paragraph-unfilled + "/** + * This is the first really + * really really really really + * really really long paragraph + * + * This is the second really really really really really really long paragraph + */" + 1 89) + (test-fill-paragraph + multi-paragraph-unfilled + "/** + * This is the first really really really really really really really long paragraph + * + * This is the second really + * really really really really + * really long paragraph + */" + 90))) + +(ert-deftest fill-paragraph-multi-paragraph-single-line-style-doc-comment () + (let + ((multi-paragraph-unfilled + "/// This is the first really really really really really really really long paragraph +/// +/// This is the second really really really really really really long paragraph")) + (test-fill-paragraph + multi-paragraph-unfilled + "/// This is the first really +/// really really really really +/// really really long paragraph +/// +/// This is the second really really really really really really long paragraph" + 1 86) + (test-fill-paragraph + multi-paragraph-unfilled + "/// This is the first really really really really really really really long paragraph +/// +/// This is the second really +/// really really really really +/// really long paragraph" + 87))) + +(ert-deftest fill-paragraph-multi-paragraph-single-line-style-indented () + (test-fill-paragraph + " // This is the first really really really really really really really long paragraph + // + // This is the second really really really really really really long paragraph" + " // This is the first really + // really really really + // really really really + // long paragraph + // + // This is the second really really really really really really long paragraph" 1 89)) + +(ert-deftest fill-paragraph-multi-line-style-inner-doc-comment () + (test-fill-paragraph + "/*! This is a very very very very very very very long string + */" + "/*! This is a very very very + * very very very very long + * string + */")) + +(ert-deftest fill-paragraph-single-line-style-inner-doc-comment () + (test-fill-paragraph + "//! This is a very very very very very very very long string" + "//! This is a very very very +//! very very very very long +//! string")) + +(ert-deftest fill-paragraph-prefixless-multi-line-doc-comment () + (test-fill-paragraph + "/** +This is my summary. Blah blah blah blah blah. Dilly dally dilly dally dilly dally doo. + +This is some more text. Fee fie fo fum. Humpty dumpty sat on a wall. +*/" + "/** +This is my summary. Blah blah +blah blah blah. Dilly dally +dilly dally dilly dally doo. + +This is some more text. Fee fie fo fum. Humpty dumpty sat on a wall. +*/" 4 90)) + +(ert-deftest fill-paragraph-with-no-space-after-star-prefix () + (test-fill-paragraph + "/** + *This is a very very very very very very very long string + */" + "/** + *This is a very very very very + *very very very long string + */")) + +(defun test-auto-fill (initial position inserted expected) + (rust-test-manip-code + initial + position + (lambda () + (unwind-protect + (progn + (let ((fill-column rust-test-fill-column)) + (auto-fill-mode) + (goto-char position) + (insert inserted) + (syntax-ppss-flush-cache 1) + (funcall auto-fill-function))) + (auto-fill-mode t))) + expected)) + +(ert-deftest auto-fill-multi-line-doc-comment () + (test-auto-fill + "/** + * + */" + 8 + "This is a very very very very very very very long string" + "/** + * This is a very very very very + * very very very long string + */")) + +(ert-deftest auto-fill-single-line-doc-comment () + (test-auto-fill + "/// This is the first really +/// really really really really +/// really really long paragraph +/// +/// " + 103 + "This is the second really really really really really really long paragraph" + "/// This is the first really +/// really really really really +/// really really long paragraph +/// +/// This is the second really +/// really really really really +/// really long paragraph" + )) + +(ert-deftest auto-fill-multi-line-prefixless () + (test-auto-fill + "/* + + */" + 4 + "This is a very very very very very very very long string" + "/* +This is a very very very very +very very very long string + */" + )) + +(defun test-indent (indented) + (let ((deindented (replace-regexp-in-string "^[[:blank:]]*" " " indented))) + (rust-test-manip-code + deindented + 1 + (lambda () (indent-region 1 (buffer-size))) + indented))) + + +(ert-deftest indent-struct-fields-aligned () + (test-indent +" +struct Foo { bar: int, + baz: int } + +struct Blah {x:int, + y:int, + z:~str}")) + +(ert-deftest indent-doc-comments () + (test-indent +" +/** + * This is a doc comment + * + */ + +/// So is this + +fn foo() { + /*! + * this is a nested doc comment + */ + + //! And so is this +}")) + +(ert-deftest indent-inside-braces () + (test-indent + " +// struct fields out one level: +struct foo { + a:int, + // comments too + b:char +} + +fn bar(x:~int) { // comment here should not affect the next indent + bla(); + bla(); +}")) + +(ert-deftest indent-top-level () + (test-indent + " +// Everything here is at the top level and should not be indented +#[attrib] +mod foo; + +pub static bar = Quux{a: b()} + +use foo::bar::baz; + +fn foo() { } +")) + +(ert-deftest indent-params-no-align () + (test-indent + " +// Indent out one level because no params appear on the first line +fn xyzzy( + a:int, + b:char) { } + +fn abcdef( + a:int, + b:char) + -> char +{ }")) + +(ert-deftest indent-params-align () + (test-indent + " +// Align the second line of params to the first +fn foo(a:int, + b:char) { } + +fn bar( a:int, + b:char) + -> int +{ } + +fn baz( a:int, // shoudl work with a comment here + b:char) + -> int +{ } +")) + +(ert-deftest indent-square-bracket-alignment () + (test-indent + " +fn args_on_the_next_line( // with a comment + a:int, + b:~str) { + let aaaaaa = [ + 1, + 2, + 3]; + let bbbbbbb = [1, 2, 3, + 4, 5, 6]; + let ccc = [ 10, 9, 8, + 7, 6, 5]; +} +")) + +(ert-deftest indent-nested-fns () + (test-indent + " +fn nexted_fns(a: fn(b:int, + c:char) + -> int, + d: int) + -> uint +{ + 0 +} +" +)) From be4f19ae7c8b72669f1201c5d009e34af2d49228 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Sat, 7 Sep 2013 00:38:23 -0400 Subject: [PATCH 8/9] Fix regression of multi-line statement indents --- src/etc/emacs/rust-mode-tests.el | 12 ++++++++ src/etc/emacs/rust-mode.el | 47 ++++++++++++++++---------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/etc/emacs/rust-mode-tests.el b/src/etc/emacs/rust-mode-tests.el index a7cb2613b9a..ac5b1b1dd98 100644 --- a/src/etc/emacs/rust-mode-tests.el +++ b/src/etc/emacs/rust-mode-tests.el @@ -378,3 +378,15 @@ fn nexted_fns(a: fn(b:int, } " )) + +(ert-deftest indent-multi-line-expr () + (test-indent + " +fn foo() +{ + x(); + let a = + b(); +} +" +)) diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el index e809a3431eb..a61d916f46f 100644 --- a/src/etc/emacs/rust-mode.el +++ b/src/etc/emacs/rust-mode.el @@ -48,13 +48,12 @@ (if (/= starting (point)) (rust-rewind-irrelevant)))) -(defun rust-first-indent-after-brace () +(defun rust-align-to-expr-after-brace () (save-excursion (forward-char) - (if (looking-at "[[:blank:]]*\\(?://.*\\)?$") - ;; We don't want to indent out to the open bracket if the - ;; open bracket ends the line - (* rust-indent-offset (rust-paren-level)) + ;; We don't want to indent out to the open bracket if the + ;; open bracket ends the line + (when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$")) (when (looking-at "[[:space:]]") (forward-to-word 1)) (current-column)))) @@ -69,7 +68,8 @@ ((looking-at "->") (save-excursion (backward-list) - (rust-first-indent-after-brace))) + (or (rust-align-to-expr-after-brace) + (* rust-indent-offset (+ 1 level))))) ;; A closing brace is 1 level unindended ((looking-at "}") (* rust-indent-offset (- level 1))) @@ -91,24 +91,25 @@ (let ((pt (point))) (rust-rewind-irrelevant) (backward-up-list) - (if (looking-at "[[({]") - (rust-first-indent-after-brace) - (progn - (goto-char pt) - (back-to-indentation) - (if (looking-at "\\") - (* rust-indent-offset (+ 1 level)) - (progn - (goto-char pt) - (beginning-of-line) - (rust-rewind-irrelevant) - (end-of-line) - (if (looking-back "[[,;{}(][[:space:]]*\\(?://.*\\)?") - (* rust-indent-offset level) - (back-to-indentation) - (if (looking-at "#") + (or (and (looking-at "[[({]") + (rust-align-to-expr-after-brace)) + (progn + (goto-char pt) + (back-to-indentation) + (if (looking-at "\\") + (* rust-indent-offset (+ 1 level)) + (progn + (goto-char pt) + (beginning-of-line) + (rust-rewind-irrelevant) + (end-of-line) + (if (looking-back + "[[,;{}(][[:space:]]*\\(?://.*\\)?") (* rust-indent-offset level) - (* rust-indent-offset (+ 1 level)))))))))) + (back-to-indentation) + (if (looking-at "#") + (* rust-indent-offset level) + (* rust-indent-offset (+ 1 level)))))))))) ;; Otherwise we're in a column-zero definition (t 0)))))) From a4697342f70bad619eae49d42c41743a67513be3 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Sat, 7 Sep 2013 00:39:38 -0400 Subject: [PATCH 9/9] Cover all cases for padding in paragraph fills as intended --- src/etc/emacs/rust-mode-tests.el | 33 ++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/etc/emacs/rust-mode-tests.el b/src/etc/emacs/rust-mode-tests.el index ac5b1b1dd98..4bfdee50c6b 100644 --- a/src/etc/emacs/rust-mode-tests.el +++ b/src/etc/emacs/rust-mode-tests.el @@ -51,20 +51,25 @@ Also, the result should be the same regardless of whether the code is at the beg (padding-len (length padding))) (loop for pad-at-beginning from 0 to 1 - for pad-at-end from 0 to 1 - with padding-beginning = (if (= 0 pad-at-beginning) "" padding) - with padding-end = (if (= 0 pad-at-end) "" padding) - with padding-adjust = (* padding-len pad-at-beginning) - with padding-beginning = (if (= 0 pad-at-beginning) "" padding) - with padding-end = (if (= 0 pad-at-end) "" padding) - for pos from (if (= 1 start-pos) 1 (+ padding-adjust start-pos)) to (+ end-pos padding-adjust) - do (rust-test-manip-code - (concat padding-beginning unfilled padding-end) - pos - (lambda () - (let ((fill-column rust-test-fill-column)) - (fill-paragraph))) - (concat padding-beginning expected padding-end))))) + do (loop for pad-at-end from 0 to 1 + with padding-beginning = (if (= 0 pad-at-beginning) "" padding) + with padding-end = (if (= 0 pad-at-end) "" padding) + with padding-adjust = (* padding-len pad-at-beginning) + with padding-beginning = (if (= 0 pad-at-beginning) "" padding) + with padding-end = (if (= 0 pad-at-end) "" padding) + ;; If we're adding space to the beginning, and our start position + ;; is at the very beginning, we want to test within the added space. + ;; Otherwise adjust the start and end for the beginning padding. + with start-pos = (if (= 1 start-pos) 1 (+ padding-adjust start-pos)) + with end-pos = (+ end-pos padding-adjust) + do (loop for pos from start-pos to end-pos + do (rust-test-manip-code + (concat padding-beginning unfilled padding-end) + pos + (lambda () + (let ((fill-column rust-test-fill-column)) + (fill-paragraph))) + (concat padding-beginning expected padding-end))))))) (ert-deftest fill-paragraph-top-level-multi-line-style-doc-comment-second-line () (test-fill-paragraph